Grails: la casella di controllo non è impostata su false


8

Sto sviluppando un'applicazione Grails (1.0.4) in cui voglio modificare una raccolta di raccolte su una singola pagina in una griglia. Ho funzionato abbastanza bene, dipende solo dalla gestione dei parametri indicizzati di Spring MVC, eccetto per una cosa:

valori booleani (o, per quello, booleani) nella griglia possono essere impostati tramite checkbox, ma non disinseriti , cioè quando controllo la casella di controllo e l'aggiornamento, il valore è impostato su true, ma in seguito, quando si modifica nuovamente, deseleziona la casella di controllo e aggiorna, rimane true.

Questo è il codice SPG della casella di controllo:

<g:checkBox name="tage[${indexTag}].zuweisungen[${indexMitarb}].fixiert" value="${z.fixiert}" /> 

E questo è il codice HTML che viene generato:

<input type="hidden" name="tage[0].zuweisungen[0]._fixiert" /> 
<input type="checkbox" name="tage[0].zuweisungen[0].fixiert" checked="checked" id="tage[0].zuweisungen[0].fixiert" /> 

Ho trovato un Grails bug che descrive esattamente questo effetto, ma è contrassegnato come corretto in 1.0.2, e il meccanismo del problema qui descritto (sottolineatura nel nome del campo nascosto è messo nel posto sbagliato) non è presente nel mio caso.

Qualche idea quale potrebbe essere la ragione?

1

Vorrei creare una piccola app di esempio che mostri il problema e collegarlo al bug di Grails (o crearne uno nuovo). Qualcuno qui potrebbe essere in grado di eseguire il debug della tua app di esempio o avrai mostrato che il bug non è stato corretto.

  0

Penso che tu intenda "mostrato" invece di "brillato". :-) 25 feb. 092009-02-25 20:35:04

  0

Troppo pigro per farlo adesso :) Probabilmente la migliore soluzione a lungo termine, però. 01 mar. 092009-03-01 13:00:26


1

Penso che la soluzione più semplice sarebbe quella di collegare un debugger e vedere perché Grails non riesce a popolare il valore. Considerando che Grails è open source, sarai in grado di accedere al codice sorgente e una volta individuata la soluzione, potrai applicare la patch alla tua versione.

Ho anche trovato questo altro bug GRAILS-2861 che menziona il problema relativo al collegamento ai booleani (vedere il commento di Marc nella discussione). Immagino che sia esattamente il problema che stai descrivendo.

  0

Sfortunatamente, tutta la magia dinamica e metaprogrammante in corso in Grails rende quasi impossibile eseguire il debug a meno che non si sappia esattamente dove cercare, probabilmente da qualche parte all'interno di Spring MVC. che non so davvero. 01 mar. 092009-03-01 13:02:16

  0

Il bug a cui ti sei collegato è una questione diversa, penso - fondamentalmente un fraintendimento basato sul diverso significato dell'attributo "valore" in HTML e graal. 01 mar. 092009-03-01 13:02:59

  0

Devo confessare che credo ancora che questi due siano correlati :-). Osservando la soluzione che hai postato di seguito sembra che il problema sia il fatto che la casella nascosta o quella NON hanno un valore da trasmettere quando il modulo viene inviato (che è discusso sul ticket). 01 mar. 092009-03-01 20:23:22

  0

La soluzione che stai postando mi fa pensare che dovresti guardare il codice del tag personalizzato e capire perché l'attributo value non è generato. Una volta che avrai questo attributo scritto in HTML, mi aspetto che questo problema venga risolto. 01 mar. 092009-03-01 20:24:47

  0

Sto cercando di ottenere l'opinione di Mr.G e Graeme sul problema qui. 01 mar. 092009-03-01 20:29:47

  0

No, il problema è che HTML non trasmette nulla per una casella di controllo deselezionata (per una selezionata, usa "on" come valore predefinito se nessuno è specificato). Il campo nascosto è una soluzione per questo. 02 mar. 092009-03-02 10:45:23

  0

E per quanto ho capito, l'attributo "valore" in grails ha un significato completamente diverso rispetto all'HTML: in Grails determina se la casella di controllo nel modulo debba essere impostata o disattivata. In HTML è la stringa che viene inviata al server se la casella è stata impostata. 02 mar. 092009-03-02 10:49:01

  0

@Michael: le caselle di controllo deselezionate NON trasmettono se deselezionate (è normale comportamento HTML), quindi se Grails si basa su qualche valore per essere lì, tutto ciò che devi fare è aggiungere una funzione javascript al modulo onsubmit che passa attraverso form.elements e imposta il valore nascosto per quelli che mancano. 02 mar. 092009-03-02 23:33:24

  0

Grails dovrebbe utilizzare il campo nascosto per dedurre che la casella di controllo con lo stesso nome (sans underscore) è deselezionata se non è presente nei parametri della richiesta - che funziona per i campi regolari, ma per qualche motivo fallisce con i campi indicizzati. 03 mar. 092009-03-03 00:28:31


0

provare questo, impostare i log per eseguire il debug, Frist provare i primi 3 se non presentano il problema, li tutto capovolgere a DEBUG:

codehaus.groovy.grails.web.servlet="error" // controllers 
codehaus.groovy.grails.web.pages="error" // GSP 
codehaus.groovy.grails.web.sitemesh="error" // layouts 
codehaus.groovy.grails."web.mapping.filter"="error" // URL mapping 
codehaus.groovy.grails."web.mapping"="error" // URL mapping 
codehaus.groovy.grails.commons="info" // core/classloading 
codehaus.groovy.grails.plugins="error" // plugins 
codehaus.groovy.grails.orm.hibernate="error" // hibernate integration 

Ciò dovrebbe consentire di vedere esattamente quando e come l'impostazione dei parametri sta fallendo e probabilmente capire un lavoro intorno.

  0

Unfortunatley, non ho trovato alcun suggerimento utilizzabile nel log - non sa come mappare il parametro "._fixiert", ma ovviamente non è presente nel modello di dominio in ogni caso, poiché è solo un'indicazione che un'assenza di ".fixiert = on" significa che dovrebbe essere impostato su false. 01 mar. 092009-03-01 13:05:53


2

Questa è la mia soluzione, in fondo una soluzione che fa manualmente ciò che i graal vincolanti i dati dovrebbero fare (ma non):

Map<String,String> checkboxes = params.findAll{def i = it.key.endsWith("._fixiert")} // all checkboxes 
checkboxes.each{ 
    String key = it.key.substring(0, it.key.indexOf("._fixiert")) 
    int tagIdx = Integer.parseInt(key.substring(key.indexOf('[')+1, key.indexOf(']'))) 
    int zuwIdx = Integer.parseInt(key.substring(key.lastIndexOf('[')+1, key.lastIndexOf(']'))) 
    if(params.get(key+".fixiert")) 
    { 
     dienstplanInstance.tage[tagIdx].zuweisungen[zuwIdx].fixiert = true 
    } 
    else 
    { 
     dienstplanInstance.tage[tagIdx].zuweisungen[zuwIdx].fixiert = false      
    } 
} 

Opere, richiede alcun cambiamento nella graal sé, ma isn' riutilizzabile (probabilmente potrebbe essere fatto con un lavoro extra).


3

Questa è la soluzione che un ragazzo di nome Julius Huang ha proposto sulla mailing list grails-user. È riutilizzabile ma si basa su JavaScript per compilare un campo nascosto con la risposta "falsa" per una casella di controllo non selezionata che l'HTML non invia.

ho hack GSP per inviare "false" quando deselezionare la casella (vero -> false) con personalizzato TagLib.

Per impostazione predefinita checkBox inviare nulla quando deselezionare, per cui uso la casella di controllo come gestore di eventi per l'invio campo nascosto invece.

"parametri" nel controller possono gestire "false" -> "true" senza alcuna modifica . per esempio. Tutto rimane stesso nel controller.

il tag personalizzato Utilizzo in GSP (campione usedfunc_F è "true"),

<jh:checkBox name="surveyList[${i}].usedfunc_F" value="${survey.usedfunc_F}"></jh:checkBox> 

Ecco ciò che il tag generare,

<input type="hidden" name="surveyList[#{i}].usedfunc_F" id="surveyList[#{i}].usedfunc_F" value="false" /> 
<input type="checkbox" onclick="jhtoggle('surveyList[#{i}].usedfunc_F')" checked="checked" /> 

Il Javascript

<script type="text/javascript"> 
function jhtoggle(obj) { 
    var jht = document.getElementById(obj); 
    jht.value = (jht.value !='true' ? 'true' : 'false'); 
} 
</script>