Announcement

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

    Dynamic ValueMap for Filter Dropdowns based on ListGrid datasource?

    I have a ListGrid and have defined the Datasource via XML. One of the columns has persons name called Officer. Is it possible to have a dropdown in the grid filter with all the unique values on it? I dont want to hard-code it as list of uniques person names may grow or shrunk. I want the dropdown list to be based on the current data loaded on grid.

    #2
    If you mean all of the values for Officer in the whole DataSource, just set an optionDataSource on the SelectItem used as filterEditorProperties for the field, and point it to an operationBinding that uses Server Summaries to perform the equivalent of a SELECT DISTINCT (see the last section on Grouping without Summarizing).

    If you want to instead show just the distinct values present in the current filtered grid, you still use an optionDataSource, but now create a clientOnly DataSource to use as the optionDataSource, and implement dataProtocol:clientCustom so that you can respond to the "fetch" DSRequest from the SelectItem with custom code. That code should go to the grid and grab all the distinct values from the grid's ResultSet. When the filter criteria on the grid change (DataChanged event), use DataSource.invalidateCache() to cause the list in the FilterEditor to be refreshed (a new DSRequest will then come in to your DataSource).

    Last case: maybe the grid isn't full loaded, so you still need to go back to the DataSource to get the full list of Officer values. You can figure out whether you're in this case because the grid's resultSet's allMatchingRowsCached() will be false. In this case, you can just implement your fetch request by issuing a fetch request to the original DataSource, again with SELECT DISTINCT. Pass along the criteria from the grid via calling listGrid.getFilterEditorCriteria().

    Comment


      #3
      Hi Isomorphic,

      thanks, I was thinking about how to solve this as well, even though it is not an issue here, yet.
      While option 1 and 3 were clear to me, #2 is new.

      Thank you & Best regards
      Blama

      Comment


        #4
        Originally posted by Isomorphic View Post
        If you want to instead show just the distinct values present in the current filtered grid, you still use an optionDataSource, but now create a clientOnly DataSource to use as the optionDataSource, and implement dataProtocol:clientCustom so that you can respond to the "fetch" DSRequest from the SelectItem with custom code. That code should go to the grid and grab all the distinct values from the grid's ResultSet. When the filter criteria on the grid change (DataChanged event), use DataSource.invalidateCache() to cause the list in the FilterEditor to be refreshed (a new DSRequest will then come in to your DataSource).
        Got any examples on this? this is what I have so far, Im new to everything SmartGWT. Looks like transformRequest is getting called before grid has any data. Also, should I be returning a Map? Definitely doing this wrong. Pls advise.

        Code:
                
        ListGrid myGrid = new ListGrid("myGridDataSource");
        
                DataSource dsi = new DataSource() {
                    @Override
                    protected Object transformRequest(DSRequest dsRequest) {
        
                        if (dsRequest.getOperationType() == DSOperationType.FETCH) {
                            ListGridRecord[] recs = grid.getRecords();
        
                            Set<String> uniqueValues = new HashSet<>();
                            for (ListGridRecord rec : recs) {
                                String value = rec.getAttribute("industry");
                                uniqueValues.add(value);
                            }
        
                            Record[] newData =
                                    uniqueValues.stream().map(value -> {
                                        Record i = new Record();
                                        i.setAttribute("industry", value);
                                        return i;
                                    }).toArray(Record[]::new);
        
                            DSResponse dsResponse = new DSResponse();
                            dsResponse.setStatus(0);
                            dsResponse.setData(newData);
        
                            processResponse(dsRequest.getRequestId(), dsResponse);
                        }
                        return dsRequest.getData();
                    }
                };
                dsi.setDataProtocol(DSProtocol.CLIENTCUSTOM);
                dsi.setClientOnly(true);
        
                ListGridField industryField = grid.getField("industry");
                industryField.setOptionDataSource(dsi);
                industryField.setValueField("industry");
        
                grid.addDataChangedHandler(dataChangedEvent -> {
                    dsi.fetchData(new Criteria());
                    grid.getDataSource().invalidateCache();
                });
        Last edited by steolan; 13 Oct 2020, 07:21.

        Comment


          #5
          No existing sample, but your question did inspire creation of one in the future.

          It's expected that you would be called as soon as the grid draws - see SelectItem.autoFetchData - data is fetched at draw for a SelectItem because it allows keyboard navigation of data while the SelectItem is closed.

          So you can turn that off to avoid the request if you want, but your code will likely still need the other branch discussed above (where allMatchingRowsCached() is false and you need to hit the server to get all the distinct values), which would also handle that early fetch.

          Comment

          Working...
          X