2013-01-17 21 views
10

Ich hatte ein seltsames Problem. Ich habe versucht, das Problem so zu isolieren, dass mein vereinfachter Code folgt.Eingabefelder halten vorherige Werte nur dann, wenn die Validierung fehlgeschlagen ist

public class MyBean { 

    private List<Data> dataList; 
    Data selectedData; 

    public MyBean() { 
    dataList = new ArrayList<Data>(); 
    dataList.add(new Data("John", 16)); 
    dataList.add(new Data("William", 25)); 
    } 

    public List<Data> getDataList() { 
    return dataList; 
    } 

    public void edit(Data data) { 
    selectedData = data; 
    } 
    public void newData() { 
    selectedData = new Data(null, null); 
    } 

    public Data getSelectedData() { 
    return selectedData; 
    } 

    public class Data { 
    String name; 
    Integer age; 
    Data(String name, Integer age) { 
     this.name = name; 
     this.age = age; 
    } 
    public String getName() { 
     return name; 
    } 
    public void setName(String name) { 
     this.name = name; 
    } 
    public Integer getAge() { 
     return age; 
    } 
    public void setAge(Integer age) { 
     this.age = age; 
    } 
    } 
} 

xhtml:

<rich:modalPanel id="pop"> 
    <h:form> 
    Name: <h:inputText value="#{myBean.selectedData.name}" required="true" id="txtName"/><br/> 
    Age : <h:inputText value="#{myBean.selectedData.age}" required="true" id="txtAge"/> 
    <a4j:commandButton value="Save"/> 
    <a4j:commandButton value="Close" onclick="Richfaces.hideModalPanel('pop');return false;"/> 
    <br/> 
    <rich:message for="txtName"/><br/> 
    <rich:message for="txtAge"/> 
    </h:form>  
</rich:modalPanel> 

<h:form> 
    <rich:dataTable value="#{myBean.dataList}" var="data"> 
    <rich:column>#{data.name}</rich:column> 
    <rich:column> 
     <a4j:commandLink value="Edit" action="#{myBean.edit(data)}" reRender="pop" oncomplete="Richfaces.showModalPanel('pop')"/> 
    </rich:column> 
    </rich:dataTable> 
    <a4j:commandButton value="New" action="#{myBean.newData()}" reRender="pop" oncomplete="Richfaces.showModalPanel('pop')"/> 
</h:form> 

Dies ist der Weg zum Fehler:

  1. Laden Sie die Seite
  2. Klicken Sie auf den Link "Bearbeiten" in der ersten Reihe (Popup-Displays)
  3. Löschen Sie im Popup-Fenster das Feld "Alter" und klicken Sie auf "Speichern". (Erforderlich angezeigte Nachricht)
  4. Klicken Sie auf Abbrechen (ohne das Feld "Alter" zu füllen)
  5. Klicken Sie auf den zweiten Link.
  6. Jetzt zeigt es irrelevante Daten (vorherige Daten). - Das ist das Problem
  7. Auch wenn ich auf "Neu" klicken, zeigt es falsche Daten.

Dies geschieht nur, wenn eine Validierung im Popup fehlgeschlagen ist.
Gibt es dafür eine Lösung?

+1

Ich weiß, das wird Ihnen nicht helfen, das Problem zu verstehen, aber Sie sollten dem Controller (der Serverseite) nicht vertrauen, um Werte in der Ansicht (der JSF-Seite) zu löschen, wenn dies mit einfachem Javascript (Dies gilt nur für den neuen ''). –

+0

Vielen Dank für Ihren Vorschlag zur Verwendung von Javascript. Ich werde es versuchen und informieren, sobald ich eine Zeit habe. – prageeth

+0

@LuiggiMendoza: Ich benutzte Javascript und hatte etwas Erfolg. Aber meine ** echte ** Situation ist ein wenig komplex und ich konnte Javascript nicht für meine aktuelle ** reale Situation ** verwenden. Aber vielen Dank für den Hinweis und ich hoffe, die Javascript-Problemumgehung als eine Antwort auf diese Frage für andere Leute zu verwenden, wenn ich eine Zeit bekam. :) – prageeth

Antwort

27

Dieses Problem ist in JSF 2 auch im Detail in der folgenden Antwort erkannt und erklärt: How can I populate a text field using PrimeFaces AJAX after validation errors occur? Wenn Sie JSF mit 2 mal, Sie verwendet OmniFaces <p:resetInput> or resetValues="true" für diesen ResetInputAjaxActionListener oder PrimeFaces' haben könnte.

Auf den Punkt müssen Sie den Zustand der EditableValueHolder Komponente löschen, wenn es Ajax-gerendert werden soll, aber die nicht in der Ajax-Ausführung enthalten ist. Um den Status zu löschen, hätten Sie in JSF 2 die bequeme Methode resetValue() verwendet, aber dies ist in JSF 1.2 nicht verfügbar und Sie müssen die 4 einzelnen Methoden setValue(null), setSubmittedValue(null), setLocalValueSet(false), setValid(true) aufrufen, um den Status zu löschen.

Um herauszufinden, welche Komponenten AJAX-gerendert werden sollen, aber nicht AJAX-ausgeführt wurden, hätten Sie in JSF 2 PartialViewContext Methoden dafür verwendet, aber dies ist nicht in JSF 1.2 verfügbar, das nicht standardisiert wurde Ajax noch. Sie müssen sich mit der RichFaces-spezifischen Ajax-API herumschlagen, um das herauszufinden. Ich kann das von oben nicht sagen, also ist hier ein Kickoff-Beispiel, vorausgesetzt, Sie kennen bereits die Komponenten, die gelöscht werden müssen. Stellen Sie sich vor, dass das Formular in Ihrem Popup hat id="popForm" und der Name Eingabefeld hat id="nameInput", hier ist, wie Sie es in der newData() Methode löschen konnte:

UIInput nameInput = (UIInput) context.getViewRoot().findComponent("popForm:nameInput"); 
nameInput.setValue(null); 
nameInput.setSubmittedValue(null); 
nameInput.setLocalValueSet(false); 
nameInput.setValid(true); 
+1

BalusC, ich schätze deine Antwort wirklich. Es hat mir geholfen, mein Problem zu lösen. Ich habe meine 'newData()' Methode entsprechend Ihrem Beispiel geändert und in meiner 'edit (data)' Methode habe ich 'nameInput.setValue (data.getName()); nameInput.setSubmittedValue (data.getName()); nameInput.setLocalValueSet (false); nameInput.setValid (wahr); '. Das funktioniert gut. Könnten Sie bitte erklären, was 'setLocalValueSet()' Methode tut. Danke noch einmal. – prageeth

+1

Es deutet JSF während der Validierungsphase an, wenn die Komponente bereits erfolgreich validiert wurde oder nicht. Das 'isValid()' gibt auch 'true' zurück, wenn die Komponente noch nicht validiert wurde. Nur wenn die Validierung fehlgeschlagen ist, wird 'false' zurückgegeben. Das 'isLocalValueSet()' gibt 'false' zurück, wenn die Komponente noch nicht validiert wurde. Wenn es erfolgreich validiert wurde, wird der lokale Wert gesetzt und 'isLocalValueSet()' wird 'true' zurückgeben. – BalusC

+0

Hallo BalusC. Gibt es etwas Ähnliches in ADF Faces? Ich möchte nicht resetValue() aufrufen, weil der Button und die inputTexts in verschiedenen Regionen liegen und auch in einem af: iterator und ich möchte eine saubere Lösung. –

1

machen Sie eine Sache auf Abbrechen Aktion setzen Sie alle Popup-Werte null. Jetzt werden beim nächsten Klick alle Werte als Standard gesetzt.

oder beim Klicken alle vorherigen Werte auf null setzen. und setze danach alle entsprechenden Werte.

0

ich hatte das gleiche Problem. Wenn Sie Primefaces verwenden, ist die Lösung so einfach wie Put resetValues="true" auf Ihrem p: commandLink oder p: commandButton, die das ausgewählte Element lädt.

+0

Die Frage lautete JSF1.2 und RichFaces (RichFaces! = PrimeFaces und die PrimeFaces-Version, die diese Funktionalität bietet, unterstützt JSF 1.2 nicht). Außerdem war es (fast) schon in der angenommenen Antwort (und jetzt ist es voll) Besser, die bestehende wel erklärte Frage beim nächsten Mal zu bearbeiten ... Aber danke für die Erinnerung an dieses Detail ... (vielleicht ist die Antwort eine Option zu). – Kukeltje