0

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.

BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555
Jörg Henke
  • 123
  • 2
  • 10
  • Please elaborate "not working" in developer's perspective, not in enduser's perspective. What exactly does not work? Sending of the HTTP request? Retrieving of the HTTP request? Restoring the JSF view? Decoding and applying the request parameters? Identifying the input component as ajax behavior source? Queueing the ajax behavior event? Evaluating the render attribute? Finding the components to be rendered? Rendering the components? Returning the HTTP response? Retrieving the HTTP response? Applying the ajax updates as instructed by HTTP response? – BalusC Apr 26 '13 at 12:39
  • Hi BalusC,firefox logs a request and this result: fyocLA6Q1X/cd964hSnkUcgqHgPWniYvCs8KJHjygbRse4XF , but the dataTable isn't updated anyway. – Jörg Henke Apr 26 '13 at 14:36
  • In addition to that: if I put the content of the composite:implementation directly into the view, the response looks this way:
    one
    two
    four
    AZuxb4F0/x3zviZwO36Td3dJlVfrOIGxp4kTr7bnDQs8rc2j
    , so the data table content is updated
    – Jörg Henke Apr 26 '13 at 14:59
  • In other words, finding the components to be rendered failed? This in turn thus means that the render client ID is wrong. What exactly did it evaluate? Why exactly did you prefix the `#{cc.clientId}:`? This is not in the same context. Why exactly did you suffix `#{cc.clientId}`? This is completely unnecessary. Just `render="table"` and `id="table"` has been sufficient. How did it fail for you? – BalusC Apr 26 '13 at 15:04
  • You saved my day. I just removed the #{cc.clientId} stuff from the composite component and all works fine. Thank you very much! I'd like to give you the solution reward, if you answer my question I can do so. – Jörg Henke Apr 26 '13 at 15:08

1 Answers1

1
<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:

Community
  • 1
  • 1
BalusC
  • 1,082,665
  • 372
  • 3,610
  • 3,555