2016-11-24 1 views
0

Ich habe einige Probleme mit JSF und Datatables konfrontiert. In meiner Bean habe ich eine Liste von Objekten, die in der Ansicht angezeigt werden, indem ich auf eine Datentabelle angewiesen bin. Das Objekt ist sehr einfach, jeder von ihnen besteht aus einer ganzen Zahl (die ID) und einem String (der Kommentar).JSF Datatable: Mehrere Zeilen reichen über eine einzige Befehlsschaltfläche

Ziel ist es, dem Benutzer die vollständige Liste der Objekte zu drucken, die gleichzeitig eine oder mehrere Zeilen (über ein h: inputtext-Feld) bearbeiten und dann seine Änderungen über eine Schaltfläche übermitteln. Und das ist das Problem. Ich habe bereits "erfolgreich" Datatables verwendet, indem ich pro Zeile eine Zeile bearbeitet habe, indem ich auf die Schaltfläche Bearbeiten/Speichern in jeder Zeile angewiesen habe. In diesem Fall ist dies jedoch nicht möglich, da der Endbenutzer mit mehr als 500 Zeilen insgesamt konfrontiert wird. Hier

ist der Code, den ich verwendet (vereinfacht und extrahiert)

Bean:

@ManagedBean 
@RequestedScope 
public class VlanBean { 

private DataModel<VlanWrapper> model; 

private List<VlanWrapper> vlans = new ArrayList<VlanWrapper>(); 

public VlanBean() { 
    vlans.add(new VlanWrapper(1, "")); 
    vlans.add(new VlanWrapper(2, "Prova2-2")); 
    vlans.add(new VlanWrapper(3, "")); 
    vlans.add(new VlanWrapper(4, "")); 
    vlans.add(new VlanWrapper(5, "")); 
    vlans.add(new VlanWrapper(6, "Prova3")); 
    vlans.add(new VlanWrapper(7, "")); 
    vlans.add(new VlanWrapper(8, "")); 
} 

public void commitChanges() 
{ 
    System.out.println("Before Model "); 

    for (VlanWrapper vw : model) 
    { 
     System.out.println("ModelOF " + vw.getId() + " - " + vw.getProject() + " - changed: " + vw.changed + ";"); 
    } 
} 

public DataModel<VlanWrapper> getModel() { 
    if (model == null) 
     model = new ListDataModel<VlanWrapper>(vlans); 
    return model; 
} 

public void setModel(DataModel<VlanWrapper> model) { 
    this.model = model; 
} 

public class VlanWrapper 
{ 
    private boolean changed; 
    private int id; 
    private String project; 

    public VlanWrapper(int id, String prj) 
    { 
     this.id = id; 
     this.project = prj; 
     changed = false; 
    } 

    public String getProject() { 
     return project; 
    } 

    public void setProject(String project) { 
     System.out.println("Setting PRJ.."); 
     changed = true; 
     this.project = project; 
    } 

    public int getId() { 
     return id; 
    } 

    public boolean isChanged() { 
     return changed; 
    } 
} 
} 

Ausblick:

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" 
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> 
<html xmlns="http://www.w3.org/1999/xhtml" 
xmlns:f="http://java.sun.com/jsf/core" 
xmlns:h="http://java.sun.com/jsf/html" 
xmlns:ui="http://java.sun.com/jsf/facelets"> 
<h:head> 
</h:head> 
<h:body> 
<f:view> 
    <h:panelGroup> 
    <h:form> 
     <h:commandButton value="Commit changes to DB" action="#{VlanBean.commitChanges}"> 
     </h:commandButton> 
    </h:form> 


    <h:dataTable value="#{VlanBean.model}" var="vlans"> 
     <h:column><f:facet name="header">ID</f:facet>#{vlans.id}</h:column> 
     <h:column><f:facet name="header">Project</f:facet> 
      <h:inputText value="#{vlans.project}" immediate="true"/> 
     </h:column> 
    </h:dataTable> 
    </h:panelGroup> 

</f:view> 
</h:body> 
</html> 

Das Problem ist, dass alle Änderungen, die ich auf der Ansicht tun sind nicht in der Bohne reflektiert und ich habe keinen nützlichen Hinweis/post around (einige, wo vorgeschlagen Ajax gezwungen Update, andere Javascript, aber ich habe keine von ihnen funktioniert und niemand war wirklich clo zu der von mir gewünschten Verwendung).

Ich habe auch versucht, für ui: wiederholen, aber ich habe das gleiche Verhalten. Irgendwelche Ideen/Vorschläge? Ich bin nicht verpflichtet, Datatable zu verwenden, also bin ich offen für andere Lösungen/Ansätze!

Dank in advace, Alberto

Antwort

0

aus dem Code, eine Warnung immer sagen, dass Ihre <h:inputText sollte ein <f:form als Elternteil haben werden sollte; es gibt keine Form, die sie umgibt, und das Formular, das Sie haben, ist nur die <h:commandButton

rund um jede Art von Iteration Mit UIComponent Sie das gewünschte Verhalten haben können, obwohl man normalerweise <h:datatable verwenden. Eine Möglichkeit, die Sie tun können, ist die folgende, obwohl Sie die Zeilen auswählen müssen, die Sie zuerst bearbeiten möchten, aber ich bin mir sicher, dass Sie die Lösung selbst finden können:

Ich habe Ihrer Entität eine weitere Eigenschaft hinzugefügt: VlanWrapper:

private boolean changed; 
private boolean edit; 
private int id; 
private String project; 

// Setter & Getter ....

Ihre Facelet so etwas wie dies sein könnte:

<h:form> 
    <h:dataTable value="#{meod.vlans}" var="v" > 

     <h:column> 
      <f:facet name="header">Id</f:facet> 
      <h:outputLabel value="#{v.id}" />      
     </h:column> 

     <h:column> 
      <f:facet name="header">Project</f:facet> 
      <h:outputLabel rendered="#{not v.edit}" value="#{v.project}" /> 
      <h:inputText rendered="#{v.edit}" value="#{v.project}" > 
       <f:ajax event="blur" execute="@this" listener="#{meod.addToEditedList(e)}" render="@all"> 
        <f:param name="vlanedit" value="#{v.id}" /> 
        <f:param name="vlanproject" value="#{v.project}" /> 
       </f:ajax> 
      </h:inputText> 
     </h:column> 

     <h:column> 
      <f:facet name="header">Edit</f:facet> 
      <h:commandButton value="Edit" action="#{meod.edit(v)}"> 
       <f:ajax render="@form" /> 
      </h:commandButton> 
     </h:column> 
    </h:dataTable>    
    <h:commandButton value="Finalize Edit" action="#{meod.editSubmit()}" /> 
</h:form> 

Der Grund, warum ich sagte, dass Sie die Zeilen auswählen müssen, die Sie bearbeiten möchten, ist, weil wenn Sie die edit Taste drücken, wird das ganze Formular aktualisiert, also spielen Sie einfach mit dem, was Sie wollen, aktualisiert und dies sollte es tun.

Die backingbean:

@ManagedBean 
@ViewScoped 
public class Meod { 

    private List<VlanWrapper> vlans; 

    public Meod() { 

     vlans = new ArrayList<>(); 

     for (int i = 0; i < 11; i++) { 

      vlans.add(new VlanWrapper(i, "Project " + i)); 
     } 
    } 

    public void addToEditedList(AjaxBehaviorEvent e) { 

     Map<String, String> params = FacesContext.getCurrentInstance().getExternalContext().getRequestParameterMap(); 

     int id = Integer.valueOf(params.get("vlanedit")); 
     String newProject = params.get("vlanproject"); 

     updateVlanInView(id, newProject); 
    } 

    private void updateVlanInView(int id, String proj) { 

     vlans.stream().filter(v -> v.getId() == id).forEach(v -> v.setProject(proj)); 
    } 

    public void edit(VlanWrapper vlan2Edit) { 
     vlan2Edit.setEdit(true); 
    } 

    public void editSubmit() { 
     vlans.forEach((v) -> v.setEdit(false)); 
    } 

    public List<VlanWrapper> getVlans() { 
     return vlans; 
    } 

    public void setVlans(List<VlanWrapper> vlans) { 
     this.vlans = vlans; 
    } 
} 

Es gibt mehrere Möglichkeiten, wie Sie dies erreichen können ...wahrscheinlich bessere Möglichkeiten, aber zusammenfassen:

  • eine Datentabelle erstellen iterieren Sie Objekte
  • Stellen Sie sicher, Ihre <h:commandXXX und EditableValueHolder s in einer Form sind.
  • Die „neue“ Eigenschaft edit ist, ob oder nicht, um zu bestimmen den Eingang statt der Ausgangstextkomponenten
  • Verwenden Sie ein DBService zu machen, die Werte zu aktualisieren, nachdem Sie geändert haben.

Hoffe das hilft.

+0

Vielen Dank für die Antwort, es klärt mich mehrere Punkte! eigentlich für den Fluss muss ich implementieren, ich werde nicht die Editier-Eigenschaft benötigen, aber es war ein sehr guter Vorschlag und Beispiel! Vor allem der Ajaxteil! – kappaalby

0

Verschieben Sie Ihr </h:form> Tag nach der Datentabelle. Dies schließt jetzt Ihre Änderungen ein und ruft nun ordnungsgemäß die Methode setProject auf.

<h:panelGroup> 
    <h:form> 
     <h:commandButton value="Commit changes to DB" action="#{VlanBean.commitChanges}"> 
     </h:commandButton> 

     <h:dataTable value="#{VlanBean.model}" var="vlans"> 
      <h:column><f:facet name="header">ID</f:facet>#{vlans.id}</h:column> 
      <h:column><f:facet name="header">Project</f:facet> 
      <h:inputText value="#{vlans.project}" immediate="true"/> 
      </h:column> 
     </h:dataTable> 
    </h:form> 
</h:panelGroup> 
+0

Danke! Es war das Stück, das ich vermisste! – kappaalby

Verwandte Themen