Announcement

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

    ListGrid select on filter change

    I have 2 ListGrids: top and bottom. The bottom grid gets filtered based on what is selected in the top grid. I did this by adding a SelectionUpdatedHandler to top that calls bottom.filterData with a criteria based on the selection. So when the user clicks on an item with a certain Category, only those matching in bottom will be displayed.

    Now, I'm trying to do the reverse: to select an item in top when the user filters using the filter editor for a specific field. For example, in the filter editor for the bottom grid's Category field, the user types 1. This should cause the bottom grid to display only items with Category 1. I also want the item with Category 1 to be selected in the top grid.

    I tried adding a FilterSubmitHandler that calls selectRecord on the top grid that matches the filter. However, this also invokes the SelectionUpdatedHandler added to top. Is there a way to tell the difference between when the user clicked a checkbox to select verses when it's done programmatically?

    #2
    The simplest thing is just to set a flag right before you make the programmatic call, and ignore the SelectionUpdatedHandler when that flag is set.

    Comment


      #3
      Thanks for the suggestion. I used it my code and it worked.

      However, I ran into a different problem. When I select some items in the top grid, the bottom grid filters based on that, which is what I want. Then when I type something into the filter editor of the bottom grid, if it matches something in the top grid, that item should be selected. That works fine except the bottom grid does not get filtered.

      For example:
      Top contains items with id 1,2,3,4
      Bottom contains items 1 thru 10
      1 and 3 are selected in top. This causes bottom to be filtered so only bottom has 1 and 3
      Now, I type 2 into bottom's filter editor. Top changes to item 2 but bottom becomes empty.

      Here is a test case I wrote: (please excuse any typos)
      Code:
      static class TestDS extends DataSource {
        TestDS(int max) {
          setClientOnly(true);
          DataSourcefield id = new DataSourceField("id", FieldType.TEXT);
          id.setPrimaryKey(true);
          addField(id);
      
          Record[] records = new Record[values.length];
          for (int i = 0; i < max; i++) {
            ListGridRecord r = new ListGridRecord();
            r.setAttribute("id", i);
            records[i++] = r;
          }
        }
      }
      
      public static ListGrid newListGrid(int max) {
        ListGrid grid = new ListGrid();
        grid.setDataSource(new TestDS(max));
        grid.setShowFilterEditor(true);
        grid.setFields(new ListGridField("id"));
        grid.setFilterOnKeyPress(true);
        return grid;
      }
      
      public void onModuleLoad() {
        final ListGrid top = newListGrid(4);
        top.setSelectionAppearance(SelectionAppearance.CHECKBOX);
        top.setSelectionType(SelectionStyle.SIMPLE);
        top.setHeight(200);
      
        final ListGrid bottom = newListGrid(10);
        bottom.setAutoFetchData(true);
        bottom.setTop(210);
        bottom.setHeight(400);
        
        top.addSelectionUpdateHandler(new SelectionUpdateHandler() {
          public void onSelectionUpdated(SelectionUpdatedEvent event) {
      	    ListGridRecord[] selectedRecords = top.getSelectedRecords();
            Criterion[] c = new Criterion[selectedRecords.length];
            int i = 0;
            for (Record r : selectedRecords) {
              c[i++] = new Criterion("id", OperatorId.EQUALS, r.getAttribute("id"));
            }
            bottom.filterData(new AdvancedCriteria(OperatorId.OR, c));
          }
        });
        
        bottom.addFilterEditorSubmitHandler(new FilterEditorSubmitHandler() {
          public void onFilterEditorSubmit(FilterEditorSubmitEvent e) {
            Criteria c = e.getCriteria();
            if (c != null) {
              if (c.isAdvanced()) {
                // if top was selected before, an AdvancedCriteria would've been created
                Criterion[] criterions = c.asAdvancedCriteria().getCriteria();
                // the last criteria contains the filter change
                Criterion lastChange = criterions[criterions.length-1];
                c = new Criteria(lastChange.getFieldName(), lastChange.getValueAsString());
              }
              // attempt to refilter bottom based on c
              bottom.clearCriteria();
              bottom.filterData(c);
              
              top.deselectAll();
              
              Map<String,String> map = c.getValues();
              if (map.contains("id")) {
                String id = map.get("id");
                for (Record r : top.getRecords()) {
                  if (id.equals(record.getAttribute("id"))) {
                    top.selectRecord(record);
                    return;
                  }
                }
              }
            }
          }
        });
        top.draw();
        bottom.draw();
        
        top.fetchData(null, new DSCallback() {
          public void execute(DSResponse resp, Object data, DSRequest req) {
            top.selectRecord(1);
            top.selectRecord(3);
          }
        });
      }
      SmartGWT 10-5-2013, GWT 2.5.1, FF 26

      Comment


        #4
        Your code in the FilterEditorSubmitHandler is explicitly wiping out the criteria on the bottom grid - it checks if the criteria are Advanced then drops everything but a branch new simple Criteria that only contains a single field/value pair.

        Comment


          #5
          Yes, that's correct. It's because when I select items in the top grid, the bottom grid gets filtered by an advanced criteria. Then when I try to edit the filter on the bottom grid, it "ands" the advanced criteria from before and whatever I typed. So I had to manually clear out the advanced criteria to leave what was typed. If I checked the debugger, it shows the the simple criteria was set correctly, but for some reason, no records are displayed.

          Actually, it would be nice if the advanced criteria was cleared to begin with when something is typed in the filter.

          Comment


            #6
            If we understand your intent correctly, the code you want in your FilterEditorSubmit handler is just bottomGrid.filterData(getFilterEditorCriteria()).

            There's no need to try to clear the existing criteria because filterData(criteria) completely replaces it.

            Also, your code for inspecting the criteria wouldn't be a reliable way to do what you're hoping (at least, not it a grid with more fields, which presumably is the real use case).

            Comment


              #7
              Yes, I'm trying to get it to filter correctly but it's not--even with trying the getFilterEditorCriteria() suggestion.

              As I mentioned before, when I print out the criteria, it shows that it's an AdvancedCriteria from the SelectionHandler ANDed with the filter editor's contents. For the example mentioned previously, it would print:

              Code:
              {_constructor=AdvancedCriteria, operator=and, criteria=[{operator=or, criteria=[{fieldName=id,operator=equals,value=1},{fieldName=id,operator=equals,value=3}], {fieldName=id,operator=iContains,value=2}]}

              Comment


                #8
                We're not seeing that result (with the simplified code we suggested). Can you grab a more recent patched build in case that's the issue?

                Comment


                  #9
                  I just updated to 4.0p 2014-01-15 and it does the same thing. I selected id 1 and 3 on top, typed 2 into the bottom's filter, and looked at event.getCriteria().getValues() and bottom.getFilterEditorCriteria().getValues(). Both showed the same thing with AdvancedCriteria as i mentioned before.

                  Comment


                    #10
                    Oh - we think we've spotted the problem. You haven't called event.cancel(), so the normal filter behavior is still occurring.

                    Comment


                      #11
                      I called event.cancel() at the top of the SubmitFilterEventHandler and then looked at bottom.getFilterEditorCriteria().getValues() and it still contains the AdvancedCriteria.

                      Comment


                        #12
                        Correct. event.cancel() means that the grid will not proceed to apply the newly edited criteria. It does not do something like clearCriteria() if that's what you were expecting.

                        Comment


                          #13
                          AdvancedCriteria for column with multiple values

                          Thanks for the suggestion. However, are requirements have changed and there is now a oneToMany relationship between the top's id and the ids in the bottom grid. So I changed the field to multiple=true

                          How do I construct a criteria so that if I selected items in the top grid, only those that contain selected ids will shown in the bottom grid?

                          Example:

                          top has 4 rows with ids 1,2,3,4

                          bottom has items with ids
                          row 1: 1,2
                          row 2: 3,4
                          row 3: 2,4
                          row 4: 1,3

                          user selects 1 and 3 from top
                          bottom should display row 1, 3, and 4

                          I tried using the Operator.Id.IN_SET but it didn't work.

                          Comment


                            #14
                            The docs for field.multiple explain in depth how criteria apply to multiple fields. Note that these are the 4.1 docs and the *server-side* behaviors are specific to 4.1, but the client side is the same.

                            As you can see, "inSet" would have the effect you seem to be looking for, but you haven't shown any code for your attempt. Possible problems would include not actually using an Array/List as the value of the multiple field (using eg a String like "1,2" won't work), or just some bug in how you formed the criteria.

                            Comment


                              #15
                              Thanks for the link to the documentation.

                              I removed the submit filter handler code and replaced the selection update handler in my original code with this:
                              Code:
                              String[] ids = new String[selectedRecords.length];
                              for (int i = 0; i < selectedRecords.length; i++) { 
                                ids[i] = selectedRecords[i].getAttribute("id");
                              }
                              bottom.filterData(new AdvancedCriteria("id", OperatorId.IN_SET, ids);
                              The bottom filter displays "1,2,3,4" when I select all from top. However, only rows that match single values, e.g,. "1", "2", etc., are matched. Rows with multiple values, e.g., "1,2", "3,4", etc., are not.

                              Comment

                              Working...
                              X