Jörg Henke
Jörg Henke

Reputation: 123

Ajax-update another component inside same composite component

When using ajax inside a composite component, the ajax feature isn't working. What's wrong with the code?

the composite component:

<composite:interface>
    <composite:attribute name="filter" required="true" type="java.lang.String" />
    <composite:attribute name="list" required="true" type="java.util.List" />
</composite:interface>
<composite:implementation>
    <h:inputText value="#{cc.attrs.filter}">
        <f:ajax event="keyup" render="#{cc.clientId}:table#{cc.clientId}" />
    </h:inputText>
    <h:dataTable id="table#{cc.clientId}" value="#{cc.attrs.list}" var="elem">
        <h:column>
            <h:outputText value="#{elem}" />
        </h:column>
    </h:dataTable>
</composite:implementation>

now the bean

@ManagedBean
@SessionScoped
public class Ajaxcc
{
    private String filter;
    private List<String> list;

    public Ajaxcc()
    {
        list = new ArrayList<String>();
        list.add("one");
        list.add("two");
        list.add("three");
        list.add("four");
    }

    public List<String> getList()
    {
        List<String> filteredList = new ArrayList<String>();
        for (String s : list)
        {
            if (filter == null || filter.trim().equals(""))
            {
                filteredList.add(s);
            }
            else if (s.contains(filter))
            {
                filteredList.add(s);
            }
        }
        return filteredList;
    }

    public String getFilter()
    {
        return filter;
    }

    public void setFilter(String filter)
    {
        this.filter = filter;
    }
}

now the view:

<h:form>
    <myCustomComponent:ajaxcc list="#{ajaxcc.list}" filter="#{ajaxcc.filter}" />
</h:form>

I'm using myfaces 2.1.10, deploying on a tomcat 7.0.39 by maven.

Expected behaviour: the list on the web site should be reduced to one, two and four whenever I press the o - button

Failure: the list isn't reduced.

What could be the solution?

BTW, if I put the content of the composite component into the view, it works correctly:

<h:form>
  <h:inputText value="#{ajaxcc.filter}">
    <f:ajax event="keyup" render="table" />
  </h:inputText>
  <h:dataTable id="table" value="#{ajaxcc.list}" var="elem">
    <h:column>
      <h:outputText value="#{elem}" />
    </h:column>
  </h:dataTable>
</h:form>

In this case pressing o reduces the list to the expected values. Besides, I found out that the response of the composite component ajax call seems to be "empty" for the data table field values; the response of the direct ajax call contains the new list.

Upvotes: 0

Views: 3494

Answers (1)

BalusC
BalusC

Reputation: 1108722

<h:inputText ...>
    <f:ajax ...render="#{cc.clientId}:table#{cc.clientId}" />
</h:inputText>
<h:dataTable id="table#{cc.clientId}" ...>

This is unnecessarily clumsy. Both components are in the same naming container (the composite itself!), so the prefix is implicitly already done by the composite itself. The suffix is valid, but just unnecessary. The composite component's own ID already enforces the uniqueness in the context of its parent naming container component. Opening the page in browser, rightclick-view source and observing the IDs in generated HTML output should already have given insights about that.

Just keep it simple:

<h:inputText ...>
    <f:ajax ...render="table" />
</h:inputText>
<h:dataTable id="table" ...>

See also:

Upvotes: 1

Related Questions