0

I have a PrimeFaces p:accordionPanel in each of whose tabs there is a form:

<p:accordionPanel id="iterator" value="#{myManagedBean.itemList}" var="item" multiple="false">

    <p:tab title="#{item.name}">

        <h:form prependid="true">

            <h:outputLabel for="field1" value="Field 1:"/>
            <p:inputText id="field1" title="Field 1" value="#{item.field1}" />

            <h:outputLabel for="field2" value="Field 12:"/>
            <p:inputText id="field2" title="Field 2" value="#{item.field2}" />

I think that it being a PrimeFaces accordionPanel is irrelevant and the behavior would be the same if it were, for example, a plain JSF h:dataTable with a form in each row.

What I would like to do (without detailed explaining why) is, once the user focus (cursor) is set in an iteration of the iterator (accordionPanel, dataTable, anything that loops over a List), notify the managed bean via AJAX what the entity (item) I am currently in. So If there are 20 rows, and consequently that number of repeating forms, each representing an item as the code exemplifies above, when I set my focus on one row's form, I would like to trigger a setter inside the managed bean setActiveEntity that will point to the entity or its ID, whichever, that identifies the row I am in.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
amphibient
  • 29,770
  • 54
  • 146
  • 240
  • 1
    `` [doesn't](https://docs.oracle.com/javaee/7/javaserver-faces-2-2/vdldocs-facelets/h/form.html) have the `prependid` attribute. It's `prependId` and defaults to `true` already. Get rid of it. – BalusC May 20 '15 at 20:58

1 Answers1

2

If you have multiple="false" (as in your case), you can use the normal PrimeFaces Accordion ajax eventsin combination with the activeIndex attribute if required. Since only one tab will be open, you can get the actual tab (name, index) in the event when it is opened)

methods in bean:

public void onTabChange(TabChangeEvent event) {
    FacesMessage msg = new FacesMessage("Tab Changed", "Active Tab: " + event.getTab().getTitle());
    FacesContext.getCurrentInstance().addMessage(null, msg);
}

public void onTabClose(TabCloseEvent event) {
    FacesMessage msg = new FacesMessage("Tab Closed", "Closed tab: " + event.getTab().getTitle());
    FacesContext.getCurrentInstance().addMessage(null, msg);
}

xhtml snippet:

<p:accordionPanel>
    <p:ajax event="tabChange" listener="#{tabbedView.onTabChange}" update=":form:msgs" />
    <p:ajax event="tabClose" listener="#{tabbedView.onTabClose}" update=":form:msgs" />
...

If you have multiple="true", you can get the opening and closing still from the ajax events, but you'll never know what is the one the user is actively doing things in. Add ajax event handlers then to your inputs and in the ajax event you can get the client id of the component that was the source of the event. This clientId will contain the 'index' of the row the source component is in. It will look something like:

iterator:1:field1

So an event handler like

public void myMethod(AjaxBehaviorEvent event){
    String clientId = ((UIComponentBase))event.getSource()).getClientId();
    // some creative string parsing here
}

Will give you the 'index' in the ajax event. The ajax tag can be

<p:ajax event="change" listener="#{myBean.myMethod}" />

Where event can be populated by something of your choice (see also What values can I pass to the event attribute of the f:ajax tag?)

A more complex solution would incorporate registering jquery eventhandlers on plain html elements and using a PrimeFaces remoteCommand to call a backingbean when a row is clicked. But you might check if h:form accepts an onclick event in an ajax tag

<h:form>
    <f:ajax event="click" listener="#{myBean.myMethod}" />
...

You'd still need to retrieve the 'index' as described above

Community
  • 1
  • 1
Kukeltje
  • 12,223
  • 4
  • 24
  • 47
  • yes but how do i construct the `f:ajax` tag that does this ? – amphibient May 20 '15 at 18:46
  • but in which form element do i nest the f:ajax ? there are multiple fields and i don't necessarily want to nest it in each one. can i nest it under the form and choose the event to be `focus` or `select` ? – amphibient May 20 '15 at 18:55
  • yes, every time the user clicks on a row, regardless of whether they change any fields – amphibient May 20 '15 at 18:57
  • when i tried `event="focus"` and `event="select"`, nested in the form, i got ` Event:select is not supported.` – amphibient May 20 '15 at 19:06
  • but is there an event i can define on the form-level and not on each input level ? it would be better to define it once for the whole form than on each element – amphibient May 20 '15 at 19:07
  • the `multiple="false"` is so that you cannot have two tabs (iterations) of the accordion panel opened at the same time. it means you can have only one open at a time – amphibient May 20 '15 at 19:11
  • Yes I know... read my answer and check the PrimeFaces showcase I linked to and what I posted as an example to – Kukeltje May 20 '15 at 19:13
  • Did the answer help? I saw you posting a 'follow-up' question. If so, please 'accept it' – Kukeltje May 20 '15 at 21:46