2

I have a p:tabview with dynamic number of tab based on a list and the attribute "dynamic=true".

    <p:tabView id="customer-master-data-tab-view" value="#{data.customers}" var="customer" dynamic="true">

Each tab has some required input fields with a p:message for each of them. Now when I submit, the validation is only performed on the current active tab. If I change to "dynamic=false", everything works fine but this will affect the performance badly since we have a lot of data on this page.

Is there a way that I can have validation on every tab of the tabview with "dynamic=true"?

nguyen anh
  • 21
  • 2

2 Answers2

0

The short answer is NO using the UI to validate using dynamic="true".

Let's say you have 4 Tabs with dynamic="true" only the first tab loaded through Ajax the other 3 tabs until they have been clicked on by the user have not been loaded into the JSF tree so there is NO way they can be validated. If you want to use this paradigm I suggest you have server side validation that checks for all the required fields on submit and throw an error from your backing bean letting the user know they have more tabs they have to fill out.

Melloware
  • 10,435
  • 2
  • 32
  • 62
0

In dynamic mode, only the tabs that have been accessed are updated, so if you want to change from tab 1 to tab 2, you can save the first time, but the second time, tab 1 does not have the data since it was not accessed after saving.

When starting the page it needs to pick the first active tab. If needed, in getActiveTabs, you can initialize activeTabs and configure the fields outside the tabView.

The init method will initialize the lastActiveTab fetching the fields from getActiveTabs and adding the first tab that is initialized.

The save button will only process the getActiveTabs fields by searching the getSaveProcess method. Every time it switches to a new tab it will add a new active tab and increase the amount of tabs it needs to process. After saving it cleans the active tabs and inserts the mandatory fields in getActiveTabs and inserts the last active tab, always repeating the same process

    
    private Set<String> activeTabs;
    private String lastActiveTab = "form:tabview:tab1";
    public void init() {
        if (!FacesContext.getCurrentInstance().isPostback()) {
            getAbasAtiva().add("form:tabView:tab1");
        }
    }
    public void onChange(TabChangeEvent event) {
        tabIndex = ((TabView) event.getSource()).getActiveIndex();
        lastActiveTab = event.getTab().getClientId();
        if (getProcess().containsKey(lastActiveTab)) {
            getActiveTabs().add(getProcess().get(lastActiveTab));
        } else {
            getActiveTabs().add(lastActiveTab);
        }
    }

    private Map<String, String> getProcess() {
        Map<String, String> process = new HashMap<>();
        process.put("form:tabview:tab2", "form:tabview:childTab2");
        return process;
    }
    public Set<String> getActiveTabs() {
        if (abasAtiva == null) {
            abasAtiva = new HashSet<>();
            abasAtiva.add("form:otherRequiredFields");
        }
        return abasAtiva;
    }

    public void setActiveTabs(Set<String> activeTabs) {
        this.activeTabs = activeTabs;
    }
    private void save(){
        //...
        setActiveTabs(null);
        if (getProcess().containsKey(lastActiveTab)) {
            getActiveTabs().add(getProcess().get(lastActiveTab));
        } else {
            getActiveTabs().add(lastActiveTab);
        }
    }
    public String getSaveProcess() {
        return String.join(", ", getActiveTabs().stream().filter(Objects::nonNull).collect(Collectors.toList());
    }

    <p:form id="form>
        <f:event type="preRenderView" listener="#{controller.init()}" />
        <p:tabView id="tabView" dynamic="true" tabindex="#{controller.tabIndex}" >
            <p:ajax event="tabChange" update="form:save" listener="#{controller.onChange}" />
            <p:tab id="tab1" title="Tab1" ></p:tab>
            <p:tab id="tab2" title="Tab2" ></p:tab>
            <p:tab id="tab3" title="Tab3" ></p:tab>
        </p:tabView>
        <p:commandButton id="save" value="Save" process="@this,#{controller.saveProcess}"  update="form" />
    </p:form>