Search code examples
jsfwebmethodswebmethods-caf

How do I create a table with a filter that filters on the server in webMethods CAF?


I have a web service that populates a table, using a SelectableListTableContentProvider, which works nicely.

However if I add a Filter Input control to the table, all it does is filter on the current table contents on the client side, ie if I'm on page 1 of 10 of the table, it doesn't go and check all values, just the ones on page 1.

How do I make a Filter Input control filter on all the values that the web service can return?


Solution

  • Here's how you do it:

    1. Create as you say a SelectableListTableContentProvider (let's call it myDataProvider), and make sure all that stuff works between the web service, the provider and the screen. This is just in case there's a mistake here and the next bit then won't work properly. Just make sure it looks normal, pages through the data properly, etc. Give the table a nice, descriptive ID.

    2. Add a Filter Input control to the screen. Set its For property to be the ID of the table.

    3. Go into your code and change myDataProvider's type from SelectableListTableContentProvider to FilterableSelectableListTableContentProvider. You will need to do it in the variable's declaration:

      SelectableListTableContentProvider myDataProvider;
      

      In two places in its getter:

      public com.webmethods.caf.faces.data.object.SelectableListTableContentProvider getMyDataProvider()  {
        if (myDataProvider == null) {
          metadataOrganisationProvider = (com.webmethods.caf.faces.data.object.SelectableListTableContentProvider)resolveExpression("#{myDataProvider}");
        }
      
        resolveDataBinding(MYDATAPROVIDER_PROPERTY_BINDINGS, myDataProvider, "myDataProvider", false, false);
        return myDataProvider;
      }
      

      AND in the managed bean config in faces-config.xml:

      <managed-bean>
      <managed-bean-name>myDataProvider</managed-bean-name>
      <managed-bean-class>com.webmethods.caf.faces.data.object.SelectableListTableContentProvider</managed-bean-class>
      <managed-bean-scope>session</managed-bean-scope>
      <managed-property>
          <description>Specifies whether the session bean expires when the pageflow is out of scope</description>
          <display-name>Expire With Page Flow</display-name>
          <property-name>expireWithPageFlow</property-name>
          <property-class>java.lang.Boolean</property-class>
          <value>true</value>
      </managed-property>
      

      In each example I'm showing what it looks like before it's changed. Just add the word Filter before SelectableListTableContentProvider.

      Now you have a filterable content provider.

    4. The screen will error at this point if you try to run it. Why? Good question. Why, Software AG? Why don't you provide a sensible default? Why do we have to pick which field to filter on, unlike the out of the box behaviour of the client-side Filter Input control, which just defaults to filtering on everything?

      Anyway. Open up the filterable provider in the Bindings pane. It looks a bit weird, because I don't think they've configured this as well as they could. Pick the Row Filter Value Binding property (its icon is a * in a box; don't know why it's not a string) and set its Data Binding property to be the Controls Scoped Variable of the correct field in the provider.

      That doesn't make sense? Okay, I'll break it down:

      1. Click on your table in the WYSIWYG view thing. Not a row in the table, the whole table. Make sure this stays selected and you don't accidentally unselect it.
      2. Click on the Row Filter Value Binding under your provider in the Bindings pane.
      3. In the Properties pane, go to the Data Binding tab and click the #{...} button to browse for the value you want.
      4. In the popup that opens, scroll to the top and open up the Controls Scoped Variables section. If this doesn't exist, go back to a) and do it properly :)
      5. Pick the value you want to filter on.
      6. Hit okay. The field will be bound to something that looks like this:

        #{result.nameOfFieldToFilterOn}
        

    Deploy and enjoy :)