Announcement

Collapse
No announcement yet.
X
  • Filter
  • Time
Clear All
new posts

    How to programmatically add a clause to FilterBuilder?

    I am trying to determine how to programmatically add a clause to a FilterBuilder, i.e. click a button and a new clause gets added to a FilterBuilder. I am assuming that FilterBuilder.addClause(FilterClause) would do the trick, but I cannot make sense out of how to construct a FilterClause such that this does what I want. I have been searching through the forums, showcase code, etc. and can't find an example that constructs a FilterClause or uses FilterBuilder.addClause. Is there an example anywhere that shows the construction of a FilterClause and invocation of FilterBuilder.addClause such that the result is the same as if the user had clicked on the + sign and added a new clause?


    As some background, I am trying to use FilterBuilder as a means to construct a nested boolean expression that is specific to my application and not equivalent to a database table query/filter condition. What I would like to be able to do is provide a list of values to pick from (equivalent to the "Country", "Government", "G8", etc. fields in the FilterBuilder showcase example), then simple choices of "Equals" or "Not Equal", and either "True" or "False". I would like the default of each to be "Equals" and "True".

    The list of items to filter on may be several hundred items long. As such, I would like to construct a separate tree, and allow for a doubleClick on a tree node (or perhaps a drag from the tree to the FilterBuilder) to add the selected item to the FilterBuilder programmatically.

    Is this possible, and is addClause the way to do it?

    Additional questions:

    1) It appears you cannot just pass a list of values to pick from in FilterBuilder. My data (the values I want to pick from to construct a filter clause) are in rows in a database table, _not_ the columns of the table. It seems that the designers of FilterBuilder did not consider this case. To work around this, I am constructing a DataSource dynamically that translates each row to a DataSourceField. Is there a better way?

    2) You can limit the available operators via setValidOperators(OperatorId.EQUALS, OperatorId.NOT_EQUAL) and limit the allowable values using setValueMap("True", "False");. But is there a way to force the default value of a new filter clause to be "True" instead of blank?

    3) Is there a way to configure FilterBuilder so that instead of presenting my list of several hundred values as a simple drop down list, it could be a Picktree or other structure that would be simpler to navigate?

    Thank you very much.

    #2
    Take a look at the "Big Filter" example in the latest nightlies. It allows you to supply a DataSource from which field definitions are fetched. The interface is a ComboBox, so the user gets type-ahead completion on the fieldName.

    As far as adding a clause or defaulting a clause to a particular value, just call setCriteria() and the FilterBuilder constructs clauses for you.

    Note that FilterBuilder.addClause() is for a very specialized use case, and the docs will soon be updated to clarify this.

    Comment


      #3
      Originally posted by Isomorphic
      Take a look at the "Big Filter" example in the latest nightlies. It allows you to supply a DataSource from which field definitions are fetched.
      OK thanks, I will look at it.

      Originally posted by Isomorphic
      The interface is a ComboBox, so the user gets type-ahead completion on the fieldName.
      Is there a way to change that to some other control when clicked, like a Picktree or a dropdown grid? The data the user will navigate through is hierarchical but does not lend itself to free-text typing so unfortunately type-ahead isn't helpful.

      Originally posted by Isomorphic
      As far as adding a clause or defaulting a clause to a particular value, just call setCriteria() and the FilterBuilder constructs clauses for you.
      OK, I tried that and it is close but the visual effect when adding to a FilterBuilder that already has lines defined is as if the FilterBuilder had been collapsed and then reconstructed line-by-line, not the same as if you clicked the + icon, which just adds a new row. It would be something closer to an "addCriteria()" or "appendCriteria()" type method I guess. The UI behavior is so nice and clean, I just want to control it programmatically! :)

      Originally posted by Isomorphic
      Note that FilterBuilder.addClause() is for a very specialized use case, and the docs will soon be updated to clarify this.
      So does that mean addClause() is off-limits? The behavior I am looking for is to programmatically achieve what happens if the user clicks on the + icon. Is there any way that is possible?


      Also, is there any way to get the filter comparison value to default to "True" instead of a blank?

      Comment


        #4
        Use setFieldPickerProperties to influence how the FormItem appears, including the ability to create your own pop-up grid or tree if desired.

        Right now, there's no incremental addCriteria() method - are you looking for this because you'd like the new clause to animate out? If you're just worried about there being kind of a "flash", create a new FilterBuilder with new criteria and put it on top, and destroy the old FilterBuilder after the new one is showing.

        Comment


          #5
          I hope you don't mind me elbowing my way into this thread. But I'd also like a way to manage the FilterBuilder criteria programmatically. A typical UI construct for me involves a ListGrid or other UI component, which the user can click on to change the filter criteria, in addition to using the FilterBuilder UI to further refine the selection. So I'd like some way for handlers on the other UI components to change or add selected criteria in the FilterBuilder.

          Comment


            #6
            I will try the 2 filterbuilder approach and see what it looks like, thanks for the suggestion, Isomorphic.

            As a general comment, it was quite painful and took a lot of trial and error to extend the existing FilterBuilder criteria by retrieving and manipulating the AdvancedCriteria object. I could not figure out a way to manipulate the AdvancedCriteria object directly, and Criteria methods like addCriteria() did not seem to work as expected.

            I am including my sample code because (1) wow this is a lot to do for what seems like it should be a simple operation, maybe there is a better way that someone could suggest, but I could not figure out and (2) if this really is the only/best way, maybe it would be helpful to someone else in the future to see a full example of how make this work.

            The following assumes you have a variable called newFieldName that holds the name of the filter to be added. I had the below code on the onDoubleClick() handler of a TreeGrid such that double-clicking on a tree node added the associated condition to the filterbuilder. For my purposes, each new filter clause would be added with an "Equals True" condition by default, as shown below.


            Code:
            // Add new filter clause to existing filter builder
            // Steps: AdvancedCriteria -> JSO AC -> JSO criteria array -> JSO extended array -> JSO flattened array -> new JSO AC -> new AC
            
            // Get current builder criteria as javascript object
            JavaScriptObject currentCriteriaJso = filterBuilder.getCriteria().getJsObj();
            
            // Get current individual criterias as array
            JavaScriptObject[] criterias = JSOHelper.getAttributeAsJavaScriptObjectArray(currentCriteriaJso, "criteria");							
            
            // Define new criteria for selected filter
            String newCriteriaString = "{\"fieldName\":\"" + newFieldName + "\",\"operator\":\"equals\",\"value\":\"True\"}";
            
            // Convert to JavaScript object
            JavaScriptObject newCriteriaItemJso = JSOHelper.eval(newCriteriaString);
            
            // Create extended array and populate with current criteria
            JavaScriptObject[] newCriterias = new JavaScriptObject[criterias.length + 1];
            
            for (int i = 0; i <criterias.length; i++ )
            {
            	newCriterias[i] = criterias[i];
            }
            
            // Add new criteria to end
            newCriterias[criterias.length] = newCriteriaItemJso;
            
            // Flatten array back to single JSO
            JavaScriptObject newCriteriaFlatJso = JSOHelper.arrayConvert(newCriterias);
            
            // Set new criteria attribute value
            JSOHelper.setAttribute(currentCriteriaJso, "criteria", newCriteriaFlatJso);
            
            // Create new advanced criteria from new criteria JSO 
            AdvancedCriteria newAc = new AdvancedCriteria(currentCriteriaJso);
            
            // Set new criteria on filterbuilder
            filterBuilder.setCriteria(newAc);

            Comment


              #7
              There's a known glitch where AdvancedCriteria.addCriteria(), which is inherited from Criteria, does the wrong thing. A fix is already scheduled. Use strictly the AdvancedCriteria APIs to correctly form and manipulate AdvancedCriteria.

              Comment


                #8
                Originally posted by Isomorphic
                Use strictly the AdvancedCriteria APIs to correctly form and manipulate AdvancedCriteria.
                Not trying to be dense here, but which APIs are you referring to which allow for _manipulating_ an existing AdvancedCriteria object directly? Looking at http://www.smartclient.com/smartgwtee/javadoc/com/smartgwt/client/data/AdvancedCriteria.html the only non-inherited methods I see of AdvancedCriteria are the 4 constructors. And since the inherited methods of Criteria should not be used as per your comment, I am not sure how you are proposing that it can be achieved when limited to use of AdvancedCriteria methods. Do you have an example that does the equivalent to what I posted (append a new condition to an existing AdvancedCriteria) _without_ doing the roundabout conversion to a JavaScriptObject?

                Comment


                  #9
                  "appending a new condition" means combining it with the existing conditions with the AND operator, so use the second constructor, passing Operation.AND, the existing AdvancedCriteria, and a new AdvancedCriteria with the new condition(s).

                  Comment

                  Working...
                  X