# JSF - Submit nach Validation-Failed



## fsicher (25. Nov 2012)

Hallo allerseits.

Ich habe in einem Projekt PrimeFaces (3.4.2) im Einsatz, aber das Problem, das ich habe, ist vermutlich JSL-Problem (oder auch nicht ...). 

Ich habe eine Seite, die für die Eingabe von Daten verwendet wird. Von 36 Inut-Felder sind ca. 20 'required'. Die Verteilung von Eingeabe-Felder habe ich mit TabView und AccordionPanel-Komponenten realisiert: sieht an sich gut aus und funktioniert auch. Was ist dann das Problem?

Wenn aus die Schaltfläche "Speichern" (commandButton) gelickt wird, wobe nich alle Inputs 'valid' sind, werden alle Felder mit 'invalid' Inhalten entsprechend markiert und anschliessend die Tab-Componente (aus TabView) geöffnet, in der die erste Komponente enthalten ist, die einen 'invalid' Inhalt hat. Wenn ich jetzt in diesem Tab alle 'invalid' Inhalte korrigiere und anschliessend auf 'Speichern' klicke, würde ich erwarten, dass danach automatisch das Tab geöffnet wird, in dem die nächste Komponente mit einem 'invalid' Inhalt enthalten ist. Leider passiert dies nicht: 


nach dem Klick auf 'Speichern' werden die zuvor korrigierten Input-Felder Inhalte validiert, die Anzeige bleibt auf dem gleichen Tab, die Markierung wird aufgehoben (da Inhalte nicht mehr 'invalid').
nach dem zweiten Klick auf 'Speichern' wird das Tab angezeigt, in dem die nächste 'invalid'-Komponente enthalten ist. 

Kurz gesagt: ich muss die Schaltfläche 'Speichern' zweimal anklicken, was ich unschön finde. Wie könnte man dies beheben?

Der Code für 'commandButton' sieht wie folgt aus: 

[XML]
<p:commandButton value="#{msg.lbl_btn_save}"
	title="#{msg.btn_data_speichern_tooltip}"
	actionListener="#{dataManagedBean.save(dataBean)}"
	update=":frm_add_data"
	oncomplete="if (args.validationFailed){tabs.select(#{dataManagedBean.activeIndex})}" />
[/XML]

Der Wert für 'activeIndex' wird in der Methode 'getActiveIndex' so manipuliert, dass er den Indexwert des nächsten 'invalid'-Tabs bekommt, falls weitere 'invalid'-Komponenten existieren sollten. ActiveIndex  wird korrekt bestimmt (durch Logging kontrolliert), leider fehlt das "Umschalten" auf das nächste 'invalid'-Tab. 

Wenn ich keine Tabs hätte, wäre dies an sich kein Problem, da alle Felder sofort sichtbar. Mit Tabs muss ich die Schaltfläche 'Speichern' einmal mehr anklicken, um die Anzeige des nächsten 'invalid' Tabs zu realisieren. 

Vielen Dank für jeden Tipp.


----------



## JimPanse (26. Nov 2012)

mach da nicht eher wizard Sinn?


----------



## fsicher (26. Nov 2012)

Hm, habe mit Vizard noch nicht gearbeitet. Aber sieht wirklich danach aus, als ob das ein guter Ansatz wäre. Ich werde es mir noch etwas genauer anschauen müssen ...

Vielen Dank.


----------



## fsicher (28. Nov 2012)

Hallo allerseits 

Habe jetzt die Implementierung mit Wizard gemacht und es funktioniert. Nun müsste ich jetzt auch in der Lage sein, ein RESET an einem beliebigen Ort (Tab) durchzuführen: 


Alle Input-Felder sollten dabei resetet werden (Textfelder leer)
Das erste Tab soll angezeigt werden.

Leider funktioniert das nur dann, wenn alle Eingaben 'valid' sind. Sobald die Validierung misslingt, funktioniert das RESETen nicht mehr. 

Ich habe es wie folgt gemacht:
- BackingBean wird resetet (SessionScoped - kann nicht ViewScoped sein)
- Umschliessendes Formular updatet


```
public void reset() {
    // reset bean: alle Felder werden auf null / 0 / false gesetzt (Meth. 'reset' in DataBean implementiert)
    ((DataBean) FacesContext.getCurrentInstance().getExternalContext()
				.getSessionMap().get("dataBean")).reset();
}
```

Kontextmenu:
[XML]
<p:contextMenu>
    <p:menuitem value="#{msg.lbl_btn_reset}" actionListener="#{dataManagedBean.reset}" update="@form" icon="ui-icon-trash" oncomplete="addWizard.loadStep(addWizard.cfg.steps[0], true)" />
</p:contextMenu>
[/XML]

Das Reseten des Beans habe ich auf wie folgt versucht, aber auch ohne Erfolg:


```
public void reset() {
    // reset bean
   FacesContext.getCurrentInstance().getExternalContext()
				.getSessionMap().put("dataBean", new DataBean());
}
```

Wie gesagt: Wenn alle eingegebene Werte 'valid' sind, funktioniert das RESETen korrekt. Aber, wie müsste man das Reseten implementieren, damit es auch dann funktioniert, wenn die Validierung misslingt?

Danke für jeden Tipp.


----------



## JimPanse (28. Nov 2012)

einfach [XML] <p:menuitem immediate="true" .../> [/XML] setzen.

immediate-attribute



> Immediate attribute, when set to true, allows a commandLink or commandButton to process the back-end logic and ignore validation process related to the fields on the page. This allows navigation to occur even when there are validation errors.


----------



## fsicher (28. Nov 2012)

Vielen Dank. 

Habe es gerade versucht, bin aber immer noch nicht ganz am Ziel ;-)

[XML]
<p:contextMenu>
    <p:menuitem value="#{msg.lbl_btn_reset}" actionListener="#{dataManagedBean.reset}" update="@form" icon="ui-icon-trash" oncomplete="addWizard.loadStep(addWizard.cfg.steps[0], true)" immediate="true"/>
</p:contextMenu>
[/XML]

Komischerweise werden alle Eingaben resetet, ausser 'valid' Eingaben in dem Tab, in dem die Validierung nicht geklappt hat. Konkret:

TAB 1: drei InputFelder --> Eingaben korrekt --> Next
TAB 2: drei InputFelder --> Eingaben korrekt --> Next
TAB 3: drei InputFelder --> die letzte Eingabe nicht korrekt --> Next -- > VALIDATION FAILD, kann nicht weiter gehen.

Wenn ich jetzt im KontextMenu 'Reset' anklicke, wird das TAB 1 angezeigt.

TAB 1: alle InputFelder leer --> Eingaben (korrekt) werden gemacht --> Next 
TAB 2: alle InputFelder leer --> Eingaben (korrekt) werden gemacht --> Next
TAB 3: InputFelder mit 'valid' Inhalten wurden nicht resetet (Inhalte weiterhin angezeigt), während das InputFeld mit dem 'invalid' Inhalt resetet wurde.

Es entsteht der Eindruck, dass die Inhalte, die validiert werden konnten (nach dem Klick auf Next), auch resetet werden können, asser der valid-Feld im TAB 3, da die Verarbeitung von Inhalten in dem Tab nicht zu Ende geführt werden konnte.


----------



## fsicher (28. Nov 2012)

Habe eine Lösung gefunden, die für mich funktioniert: *resetInput*

[XML]
<h:form id="frm_data">

...

<p:contextMenu>

    <p:menuitem value="#{msg.lbl_btn_reset}" actionListener="#{dataManagedBean.reset}" update="@form" icon="ui-icon-trash" oncomplete="addWizard.loadStep(addWizard.cfg.steps[0], true)" immediate="true">
        <p:resetInput target="frm_data" /> 
    </p:menuitem>

</p:contextMenu>

....

</h:form>
[/XML]

Mehr dazu: 
PrimeFaces - ShowCase


----------

