Announcement

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

    Problem with groups not re-sorted at SortDirection-change under some circumstances

    Hi Isomorphic,

    please see this testcase (v10.0p_2015-05-21) which closely resembles my application setup.
    When you click the column headers, the data in the groups is resorted accordingly, but the groups themselves are not. Note that I do use ListGrid.setSortByGroupFirst(true) but do not use ListGrid.setGroupSortDirection(), so they should be resorted.

    From my gut feeling creating the testcase this is somehow related to datatypes and datatype-conversion.

    It does not matter if the ListGrid is set up with setXState() or setSort(), but is does make a difference if inital sorting is ASC or DESC (see the first two buttons and the 1st group for each).

    BuiltInDS.java:
    Code:
    package com.smartgwt.sample.client;
    
    import com.google.gwt.core.client.EntryPoint;
    import com.smartgwt.client.core.KeyIdentifier;
    import com.smartgwt.client.data.DataSource;
    import com.smartgwt.client.data.SortSpecifier;
    import com.smartgwt.client.types.GroupStartOpen;
    import com.smartgwt.client.types.SortDirection;
    import com.smartgwt.client.util.PageKeyHandler;
    import com.smartgwt.client.util.Page;
    import com.smartgwt.client.util.SC;
    import com.smartgwt.client.widgets.IButton;
    import com.smartgwt.client.widgets.events.ClickEvent;
    import com.smartgwt.client.widgets.events.ClickHandler;
    import com.smartgwt.client.widgets.grid.ListGrid;
    import com.smartgwt.client.widgets.grid.ListGridField;
    import com.smartgwt.client.widgets.layout.HLayout;
    import com.smartgwt.client.widgets.layout.VLayout;
    
    public class BuiltInDS implements EntryPoint {
    	private VLayout vL;
    	private TestGrid tG;
    	private HLayout hL;
    
    	public void onModuleLoad() {
    		KeyIdentifier debugKey = new KeyIdentifier();
    		debugKey.setCtrlKey(true);
    		debugKey.setKeyName("D");
    
    		Page.registerKey(debugKey, new PageKeyHandler() {
    			public void execute(String keyName) {
    				SC.showConsole();
    			}
    		});
    
    		vL = new VLayout(5);
    		vL.setPadding(20);
    		vL.setWidth100();
    		vL.setHeight100();
    		tG = new TestGrid("setSortDesc");
    
    		hL = new HLayout(5);
    		hL.setHeight(40);
    		IButton reloadSetSortAsc = new IButton("Reload SetSortAsc");
    		reloadSetSortAsc.setWidth(150);
    		reloadSetSortAsc.addClickHandler(new ClickHandler() {
    			@Override
    			public void onClick(ClickEvent event) {
    				vL.removeChild(tG);
    				tG.markForDestroy();
    				tG = new TestGrid("setSortAsc");
    				vL.addMember(tG, 0);
    			}
    		});
    		IButton reloadSetSortDesc = new IButton("Reload SetSortDesc (Default)");
    		reloadSetSortDesc.setWidth(150);
    		reloadSetSortDesc.addClickHandler(new ClickHandler() {
    			@Override
    			public void onClick(ClickEvent event) {
    				vL.removeChild(tG);
    				tG.markForDestroy();
    				tG = new TestGrid("setSortDesc");
    				vL.addMember(tG, 0);
    			}
    		});
    		IButton reloadSetStates = new IButton("Reload SetStates");
    		reloadSetStates.setWidth(150);
    		reloadSetStates.addClickHandler(new ClickHandler() {
    			@Override
    			public void onClick(ClickEvent event) {
    				vL.removeChild(tG);
    				tG.markForDestroy();
    				tG = new TestGrid("useStates");
    				vL.addMember(tG, 0);
    			}
    		});
    		IButton getFieldState = new IButton("Get FieldState");
    		getFieldState.addClickHandler(new ClickHandler() {
    			@Override
    			public void onClick(ClickEvent event) {
    				SC.say("FieldState", tG.getFieldState());
    			}
    		});
    		IButton getSortState = new IButton("Get SortState");
    		getSortState.addClickHandler(new ClickHandler() {
    			@Override
    			public void onClick(ClickEvent event) {
    				SC.say("SortState", tG.getSortState());
    			}
    		});
    
    		hL.addMembers(reloadSetSortAsc, reloadSetSortDesc, reloadSetStates, getFieldState, getSortState);
    		vL.addMembers(tG, hL);
    		vL.draw();
    	}
    
    	private class TestGrid extends ListGrid {
    		StatusLGF status;
    		ListGridField commonName;
    		ListGridField diet;
    		ListGridField lifeSpan;
    
    		public TestGrid(String mode) {
    			super();
    			setAutoFetchData(false);
    			setGroupStartOpen(GroupStartOpen.ALL);
    			setSortByGroupFirst(true);
    
    			setDataSource(DataSource.get("animals"));
    
    			status = new StatusLGF("status");
    			status.setHidden(true);
    
    			commonName = new ListGridField("commonName");
    			diet = new ListGridField("diet");
    			lifeSpan = new ListGridField("lifeSpan");
    
    			setGroupByField(status.getName());
    			setFields(status, commonName, diet, lifeSpan);
    
    			if (mode.equals("useStates")) {
    				setFieldState("[{name:\"status\",visible:false},{name:\"commonName\"},{name:\"diet\"},{name:\"lifeSpan\"}]");
    				setSortState("({fieldName:\"diet\",sortDir:\"descending\",sortSpecifiers:[{property:\"diet\",direction:\"descending\"}]})");
    			} else if (mode.equals("setSortDesc")){
    				setSort(new SortSpecifier[] { new SortSpecifier(diet.getName(), SortDirection.DESCENDING) });
    			} else if (mode.equals("setSortAsc")){
    				setSort(new SortSpecifier[] { new SortSpecifier(diet.getName(), SortDirection.ASCENDING) });
    			}
    			fetchData();
    		}
    	}
    }
    StatusLGF.java:
    Code:
    package com.smartgwt.sample.client;
    
    import com.smartgwt.client.widgets.grid.GroupNode;
    import com.smartgwt.client.widgets.grid.GroupTitleRenderer;
    import com.smartgwt.client.widgets.grid.GroupValueFunction;
    import com.smartgwt.client.widgets.grid.ListGrid;
    import com.smartgwt.client.widgets.grid.ListGridField;
    import com.smartgwt.client.widgets.grid.ListGridRecord;
    import com.smartgwt.client.widgets.grid.SortNormalizer;
    
    public class StatusLGF extends ListGridField {
    	final String sortField;
    
    	public StatusLGF(String name) {
    		super(name);
    		sortField = "lifeSpan";
    
    		setSortNormalizer(new SortNormalizer() {
    			@Override
    			public Object normalize(ListGridRecord record, String fieldName) {
    				if (record.getAttributeAsInt(sortField) == null)
    					return new Integer(0);
    				else
    					return record.getAttributeAsInt(sortField);
    			}
    		});
    
    		setGroupValueFunction(new GroupValueFunction() {
    			@Override
    			public Object getGroupValue(Object value, ListGridRecord record, ListGridField field, String fieldName, ListGrid grid) {
    				if (record.getAttributeAsInt(sortField) == null)
    					return new Integer(0);
    				else
    					return record.getAttributeAsInt(sortField);
    			}
    		});
    
    		setGroupTitleRenderer(new GroupTitleRenderer() {
    			@Override
    			public String getGroupTitle(Object groupValue, GroupNode groupNode, ListGridField field, String fieldName, ListGrid grid) {
    				int i = groupNode.getGroupMembers().length;
    				String groupName = "Lifespan: " + groupNode.getGroupMembers()[0].getAttributeAsString(sortField) + " years";
    				return groupName + " (" + i + ((i == 1) ? " animal)" : " animals)");
    			}
    		});
    	}
    }
    Testcase is created with v10.0p_2015-05-21 and FF26 Dev Mode, but in my application the issue shows up deployed in GC42/FF26/IE11 as well.

    Best regards
    Blama

    #2
    This is not related to this thread, is it?

    Comment


      #3
      Hi Isomorphic,

      do you have an update for this one? Here you said you wanted to update this thread as well.

      Best regards
      Blama

      Comment


        #4
        Apologies, we see the issue and we're looking into it - update to follow.

        Comment


          #5
          We've made a change that should address this for builds dated June 11 and later.

          Comment


            #6
            Hi Isomorphic,

            thanks a lot. I'll retest tomorrow.

            Best regards
            Blama

            Comment


              #7
              @Blama - note that, whilst we have indeed fixed automatic group-header sorting according to the direction of some other sorted field, your particular test case will still not work as-is.

              This is because your custom sorting and grouping overrides are set on one field, "status", but they return the value of another field, "lifeSpan" - and that second field is not available on group-header records, because it's not actually grouped.

              You'd need to update your custom handlers to detect that the passed record is a group-header and return the value from its first child, for instance.

              Comment


                #8
                Hi Isomorphic,

                thanks for fixing (although I'm not sure what you changed, because it worked for me besides in this case IMHO).

                Is your last post about the same effect as in this thread?

                If so, I can see on the record parameter in
                Code:
                setSortNormalizer(new SortNormalizer() {
                	@Override
                	public Object normalize(ListGridRecord record, String fieldName) {
                		if (record.getAttributeAsInt(sortField) == null)
                			return new Integer(0);
                		else
                			return record.getAttributeAsInt(sortField);
                	}
                });
                that there are:
                • record.getIsGridSummary()
                • record.getIsGroupSummary()

                but no record.getIsGroupNode(), which is on ListGrid.isGroupNode().
                Could you either move/copy this method to ListGridRecord or make ListGrid.isGroupNode() static?
                As you can see I'm using a separate class for my ListGridField and I can't find a method record.getListGrid(), so I can't call record.getListGrid().isGroupNode(record).

                Of course I could pass the ListGrid to my subclass, but I don't think that's the correct way. Or is it?

                Best regards
                Blama

                Comment


                  #9
                  Hi Isomorphic,

                  could you explain the further processing as well?

                  Let's say I can call myListGrid.isGroupNode(record) in my SortNormalizer. What's next then? It seems I'm not able to cast or convert record to a GroupNode instance. But I need to do so to call myGroupNode.getGroupMembers()[0] to access the 1st member.

                  Best regards
                  Blama

                  Comment


                    #10
                    Hi Blama,
                    You're basically going to need to get at the ListGrid in some way so you can call the helpful APIs you need, like isGroupNode, and getGroupTree [for working with children, etc]

                    You can do this with application code - exactly how you structure it is up to you. You could store the ListGrid on your ListGridField subclass as a member variable or similar, or you could do something like use an inner class structure.

                    We're discussing whether it makes sense to tweak the framework APIs to provide some kind of accessor here to simplify this in the future, but even if we do so, this would not be something we'd be backporting to an existing release (like 5.0)

                    Regards
                    Isomorphic Software

                    Comment

                    Working...
                    X