简体   繁体   中英

p:datatable not refreshed correctly after data modification in p:dialog

Ok, tried to shorten a bit and put the code at the end of the post. Thank you for your answers.

After reading quite a few questions/answers on the subject and not finding any solution, here is my issue. I tried to be as concise as possible so I might have truncated some code, feel free to ask for details. I am also quite new to the JSF, primefaces world.

I develop evolutions/fixes on an existing web application based on Spring/Hibernate/Primefaces. The user interface contains a tabview with some p:datatable : companies, users in my case.

So here is my use case:

  • In 'formCompany', a button displays the dialog 'createCompany'.

  • I create a company 'aaaa/aaaa' (name and code are mandatory for societeEntity) -> the company is added in 'CompaniesTable'

  • I create a user associated to this company 'john'/'aaaa' (name and company are mandatory fields for utilisateurEntity) -> the user is created and displayed in 'userTable' with the company name 'aaaa'

  • I modify the name to 'bbbb' of the company and save it -> the company name is not updated in 'userTable'

What I suspect is that userTable is not refreshed from the database with the 'update' attribute of the commandButton. I guess that the 'update' attribute on ":panelBas:formUser:userTable" works fine but only on client side.

What I expect is that the datatable containing the users will be refreshed with the new company name 'bbbb'.

The tricks I tried :

  • update attribute on p:commandButton => fail
  • reaching userTable from p:commanbButton.oncomplete with its widgetVar id and calling an hypothetic 'refresh/reload/update' method, using PF('userTable') => fail (primefaces documentation is not really helping...)

Here is the code of the button that saves the company :

<p:commandButton value="Save" update="companyNameMsg companyCodeMsg :panelBas:formCompany:CompaniesTable **:panelBas:formUser:userTable**" ajax="true"
    actionListener="#{companyDialog.save}" icon="ui-icon-disk"
    **oncomplete="if(args &amp;&amp; !args.validationFailed) { PF('createCompany').hide(); }"** />

The component p:datatable does not seem to have a method to reload data from the server. So the question is how can I update my user datatable after saving a company in a backing bean ?

The code below shows the xhtml page containing the tabview, dialogs, datatables, ...

main.xhtml

<p:tabView id="panelBas" widgetVar="wvPanelBas" activeIndex="#{searchDialog.activeIndex}">
    <p:tab title="Companies">
        <h:form id="**formCompany**">
            <p:dataTable id="CompaniesTable" value="#{companyDialog.companyList}" var="item3" lazy="false"
                tableStyle="text-align: center;width:auto" paginator="true" rowsPerPageTemplate="5,10,15,20,30,50,100" rows="15"
                sortBy="#{item3.nom}" sortOrder="ascending" filteredValue="#{companyDialog.companyFilteredList}">
                ...
            </p:dataTable>
        </h:form>
    </p:tab>

    <p:tab title="Users">
        <h:form id="formUser">
            <p:dataTable id="userTable" widgetVar="wvUserTable" **value="#{userDialog.utilisateurList}"** var="item2" lazy="false" 
                tableStyle="text-align: center;width:auto" paginator="true" rowsPerPageTemplate="5,10,15" rows="10"
                sortBy="#{item2.nom}" sortOrder="ascending" filteredValue="#{userDialog.utilisateurFilteredList}">

                **<!-- This value is not updated when associated company's name is modified-->
                <p:column filterBy="#{item2.societe.nom}" sortBy="#{item2.societe.nom}" headerText="Company">
                    <h:outputText value="#{item2.societe.nom}" />
                </p:column>**
                ...
                <p:column filterBy="#{item2.nom}"  sortBy="#{item2.nom}" headerText="Nom" sortOrder="ascending">
                    <h:outputText value="#{item2.nom}" />
                </p:column>
            </p:dataTable>
        </h:form>
    </p:tab>
</p:tabView>

<!-- This dialog allows to modify company data -->
<p:dialog header="New Company" widgetVar="createCompany" id="createCompany" resizable="true" modal="true" width="500" showEffect="clip" hideEffect="clip">
    <h:form>
        ...
        <!-- Company modification form -->
        <p:commandButton value="Save" update="companyNameMsg companyCodeMsg :panelBas:formCompany:CompaniesTable **:panelBas:formUser:userTable**" ajax="true"
            actionListener="#{companyDialog.save}" icon="ui-icon-disk"
            **oncomplete="if(args &amp;&amp; !args.validationFailed) { PF('createCompany').hide(); }"** />
    </h:form>
</p:dialog>

Here is the code of the beans:

CompanyDialog.java

@Component("companyDialog")
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class CompanyDialog {
    // Managed property used by datatable attribute 'value'
    @ManagedProperty("#{companyList}")
    private List<SocieteEntity> companyList;

    // Managed property used by datatable attribute 'filteredValue'
    @ManagedProperty("#{companyFilteredList}")
    private List<SocieteEntity> companyFilteredList;

    @ManagedProperty("#{societeEntity}")
    private SocieteEntity societeEntity;

    @Override
    public void save() {
        ...
    }
}

UserDialog.java

@Component("userDialog")
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserDialog {
    // Managed property used by datatable attribute 'value'
    @ManagedProperty("#{utilisateurList}")
    private List<UtilisateurEntity> utilisateurList;

    // Managed property used by datatable attribute 'filteredValue'
    @ManagedProperty("#{utilisateurFilteredList}")
    private List<UtilisateurEntity> utilisateurFilteredList;

    @ManagedProperty("#{utilisateurEntity}")
    private UtilisateurEntity utilisateurEntity;

    public void recherche() {
        // Fills the managed property utilisateurList (used by the datatable)
        ...
    }
}

Thank you in advance and have a nice day.

Your question is: "how can I update my user datatable after saving a company ?"

In button in your dialog in jsf try this:

<h:commandButton id="ok" value="OK">
    <p:ajax click="messagesDialog.hide()" 
    update="@all"/>
</h:commandButton>

in update target first all, try use @form, if doesnt work, use @all

If doesnt work try use imediate="true", imatiate true, this will change order lifecycle, maybe solve your problem if before sugestions doesnt worked. I think your are question is simple, you don't should write many text.

So I digged the solution with injected beans and made it work.

The idea is in that link : Can I call multiple methods from <p:ajax event=select listner=method1, metho2>? .

I am not sure if this method is very clean regarding the annotations...

I injected UserDialog bean in CompanyDialog bean like this :

@Component("companyDialog")
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class CompanyDialog {
    @Inject
    private UserDialog userDialog;

    // When I update a company, the list userDialog.utilisateurList of users is reloaded in userDialog
    public void save() {
        // ...
        userDialog.recherche();
    }
}

@Component("userDialog")
@Scope(value = WebApplicationContext.SCOPE_SESSION, proxyMode = ScopedProxyMode.TARGET_CLASS)
public class UserDialog {
    @ManagedProperty("#{utilisateurList}")
    private List<UtilisateurEntity> utilisateurList;

    // Fills the list utilisateurList
    public void recherche() {
        // ...
    }
}

If any improvement can be made, feel free to give any advice.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM