Announcement

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

    ListGrid Group Summary - how to access parent group within SummaryFunction

    SmartClient Version: SC_SNAPSHOT-2011-08-02/LGPL Development Only (built 2011-08-02)
    Browser : IE9

    We need help on two things regarding Grid group summary title field:

    1. Is it possible to access the parent group within summary function so that we can construct custom title with group info appened? So for ex, in attached sample grid it becomes, "Totals(Currency-GBP)" as oppossed to just "Totals" for all summary records.

    2. In group summary row, can field be spanned over to multiple columns. So that we get more room to constrcut the title.

    Please see attached sample grid for context. Any help on on this will be greatly appreciated.
    Attached Files

    #2
    1. Is it possible to access the parent group within summary function so that we can construct custom title with group info appened? So for ex, in attached sample grid it becomes, "Totals(Currency-GBP)" as oppossed to just "Totals" for all summary records.
    The parent level group node is not passed into the function - however you should be able to look at the actual data directly. In your example, every record in the group will have that same currency value set, so you can simply check for that attribute on the first record in the list. And if you're having the grouping be changed dynamically, you should be able to look at the grid's groupBy fields to determine which properties you're interested in.

    2. In group summary row, can field be spanned over to multiple columns. So that we get more room to constrcut the title.
    This is not currently supported. Your options here would be to expand the column horizontally, allow wrapping and expand the row vertically (autoFitRecordHeights:false), or come up with some alternative UI, such as re-displaying the currency in a different field, or showing it in a hover prompt.

    Regards
    Isomorphic Software

    Comment


      #3
      Thanks for a quick response.

      1. In our case we could have upto 4 level of groups, and for each group summary, label should be "Totals-<groupName>". How would it work if mulitple groups map to same records, for ex., in attached sample grid, Currency-AUD and Date-31/01/2013 has same records?

      Comment


        #4
        Code:
        1. In our case we could have upto 4 level of groups, and for each group summary, label should be "Totals-<groupName>". How would it work if mulitple groups map to same records, for ex., in attached sample grid, Currency-AUD and Date-31/01/2013 has same records?
        We're not understanding exactly what you're asking here. If you have multiple levels of grouping, you won't see the same records showing up in more than one place - each record will fit in one folder only. So if you're grouping by fieldA, then fieldB, you might see a layout like this:
        Code:
        (Group) fieldA valueA
           (Inner Group) fieldB value 1
              Record with fieldA:"A", fieldB:1
              Record with fieldA:"A", fieldB:1
              [Inner Group Summary]
           (Inner Group) fieldB value 2
              Record with fieldA:"A", fieldB:2
              [Inner Group Summary]
           [Group Summary]
        (Group) fieldA valueB
           (Inner Group) fieldB value 1
              Record with fieldA:"B", fieldB:1
              [Inner Group Summary]
           [Group Summary]
        So it should be a simple matter of looking at the field value[s] of the records within a group to determine what group(s) the records are in.

        Comment


          #5
          Thanks.

          1. Debugging through hosted mode, I noted that summary function is being called many times(more than I expected it to be, i.e. once per group), and it gets different number of records passed in (starting from 1 to number of records). You think this could be because we are using old version 2.5 of GWT.

          2. Assuming it works as you described in your post, wouldn't same number of records be passed for summary groups for field A, B & C.

          Code:
          (Group) fieldA valueA
             (Inner Group) fieldB value 1
                (Inner Group) fieldC value 2
                Record with fieldA:"A", fieldB:1, fieldC:2
                Record with fieldA:"A", fieldB:1, fieldC:2
                [Inner Group Summary fieldC]
                [Inner Group Summary fieldB]
             [Group Summary fieldA]
          Thanks for your help on this.

          Comment


            #6
            1) It is possible that the summary function validly gets called more often than you're expecting. The summary is re-evaluated in a number of cases, basically whenever the data may have changed, or the grid is being "refreshed" for display.
            If you think you may be seeing more calls to the method than make sense (or getting passed unexpected data), show us a test case and we'll take a look.

            2) Our understanding was that given a grid like this:
            Code:
            [Group header: "Currency AUD"]
                [Inner Group Header: "Date 31/01/2013"]
                    <record object matching this grouping>
                [Date Inner group summary]
             [Currency group summary]
            You want to have the group summary row[s] have a field which displays text including details of the grouping.
            So presumably the "Date Inner Group Summary" might have a field which shows the value "Totals (31/01/2013 -AUD):"
            And the "Currency group summary" would show "Totals (AUD):"

            Is that correct?

            If so it would seem like the parameters passed to getGroupSummary() would allow this.
            The difficulty would be that for the "inner group" you don't have a direct reference to what the parent group is. However, you could presumably look at the grid to determine what the current grouping is, and use this.

            Here's a proof of concept you could drop into this example:
            Code:
            isc.ListGrid.create({
                ID: "countryList",
                width:600, height:224,
                alternateRecordStyles:true, cellHeight:22,
                dataSource: countryDS,
                showGroupSummary:true,
                // display a subset of fields from the datasource
                fields:[
                    {name:"countryName"},
                    {name:"government",
                    width:350,
                    getGroupSummary:function (records, field, groupNode) {
                        var gridGroups = countryList.getGroupByFields(),
                            currentGroup = groupNode.groupName,
                            parentGroups = [];
                        
                        var result = "Totals (";
                        for (var i = 0; i < gridGroups.length; i++) {
                            if (gridGroups[i] == currentGroup) {
                                result += currentGroup + "[" + groupNode.groupValue + "]):";
                                break;
                            } else {
                                // Look directly at a record - they should all match
                                // Note that if you had custom 'getGroupValue()' on a field, you
                                // should technically call that here too.
                                var groupValue = records[0][gridGroups[i]];
                                result += gridGroups[i] + "[" + groupValue + "] - "
                            }
                        }
                        
                        return result;
                    }
                    },
                    {name:"continent", summaryFunction:"count"},
                    {name:"countryCode", title:"Flag", width:40, type:"image", imageURLPrefix:"flags/16/", imageURLSuffix:".png", canEdit:false}
                ],
                groupStartOpen:"all",
                groupByField: ['continent', 'countryName'],
                autoFetchData: true
            })

            Comment


              #7
              (2) Your illustraion about the grid is correct, this is how we want grid summary titles to be rendered. However we are not able to understand the code snippet you have given, we are using Smart GWT v2.5. Please advise.

              Comment


                #8
                This is working proof-of-concept code - can you clarify what you don't understand?

                Note that reading the docs for all the referenced properties and methods may help.

                Comment


                  #9
                  We are only familiar with smartGWT Java api, however above you referring to JavaScript code. This is what we not able to understand, also there is no function called getGroupSummary(..) in http://www.smartclient.com/smartgwt/...GridField.html

                  Please advise.
                  Last edited by nayyer.kamran; 20 Feb 2013, 10:48.

                  Comment


                    #10
                    Oh - sorry for the confusion - of course this would be confusing.
                    Moreover, it appears this particular override point isn't present in SmartGWT.
                    We can wrap it for you - but would you be able to update to a new nightly build (on the 2.5 branch if necessary) to pick it up?

                    Let us know - if updating your build isn't an option we can put together equivalent code to set up the same JavaScript API using JSNI and give you that to integrate into your application - though of course this would not be our preferred approach as it's harder to maintain, etc.

                    Comment


                      #11
                      Thanks for your response. This is what we thinking, since our application is already in production, so upgrading to new version would need proper regression testing. So JSNI option woule be prefered at this stage. However we would like to use pure Java solution in long term, and will progress upgrade in background. So please provide both, if possible. Thanks.

                      Comment


                        #12
                        We're putting something together. We should have an update for you later today.

                        Comment


                          #13
                          Ok - this functionality will be built into 4.0d going forward, available via an API "listGridField.setGroupSummaryCustomizer()".

                          Here's a JSNI equivalent you can use against prior versions.

                          Note that we've written this all into a single entryPoint class with some inline classes etc to simplify the demo but you can break it up as makes sense within your app. You'll probably want to make some other changes too - consider this a starting point / proof of concept to get you going.

                          Also note that this should be considered a temporary solution for your current usage. We're not guaranteeing the final API will look exactly like this, and you should definitely plan to migrate to it when you do upgrade.

                          Please let us know if this doesn't get you the results you need

                          Thanks
                          Isomorphic Software

                          Code:
                          package com.smartclient.test.client.feb_13;
                          
                          import com.google.gwt.core.client.EntryPoint;
                          import com.smartgwt.client.data.Record;
                          import com.smartgwt.client.types.SummaryFunctionType;
                          import com.smartgwt.client.widgets.grid.GroupNode;
                          import com.smartgwt.client.widgets.grid.ListGrid;
                          import com.smartgwt.client.widgets.grid.ListGridField;
                          import com.smartgwt.client.widgets.grid.ListGridRecord;
                          
                          public class GroupSummaryDemo implements EntryPoint {
                          	
                          	/**
                          	* Abstract class for creating custom group summaries (implemented as an inner class for demo purposes)
                          	*  
                          	* If {@link ListGrid#getShowGroupSummary()} is true, and this method is specified it will be
                          	* called to generate the field summary value to be displayed for each group level summary row.
                          	* Note that this is called instead of making use of the ListGridField.summaryFunction.
                          	* <P>
                          	* 
                          	*/
                          	public static abstract class GroupSummaryCustomizer {
                          	       
                          	       /**
                          	        * 
                          	        * @param recordsrecords for which a summary is being generated (so all records in the group).
                          	        * @param field pointer to the field for which summary value is being generated
                          	        * @param groupNode object with specified groupValue and groupName for this group
                          	        * @return This method may return an array of results - in this case the group will show multiple summary
                          	    *         rows, with each entry in the array showing up in a different record.
                          	        */
                          	   public abstract Object[] getGroupSummary(Record[] records, ListGridField field, GroupNode groupNode);
                          	}
                          	
                          	/**
                          	 * ListGridField subclass with JSNI API for customizing group summary
                          	 * (implemented as an inner class for demo purposes)
                          	 */
                          	public static class SummaryEnabledField extends ListGridField {
                          
                          		/**
                          	    *
                          	    * @param groupSummaryCustomizer the group summary customizer
                          	    */
                          	   public native void setGroupSummaryCustomizer(GroupSummaryCustomizer groupSummaryCustomizer) /*-{
                          	       var self = this.@com.smartgwt.client.core.DataClass::getJsObj()();
                          	       self.getGroupSummary = $debox($entry(function(records, field, groupNode) {
                          	       	
                          	       		var recordsJ = null;
                          	       		if (records != null) {
                          	       			recordsJ = @com.smartgwt.client.widgets.grid.ListGridRecord::convertToRecordArray(Lcom/google/gwt/core/client/JavaScriptObject;)(records);
                          	       		}
                          	           var fieldJ          = @com.smartgwt.client.widgets.grid.ListGridField::getOrCreateRef(Lcom/google/gwt/core/client/JavaScriptObject;)(field);
                          	           var groupNodeJ      = groupNode == null ? null : @com.smartgwt.client.widgets.grid.GroupNode::new(Lcom/google/gwt/core/client/JavaScriptObject;)(groupNode);
                          
                          	           
                          	           var result = groupSummaryCustomizer.@com.smartclient.test.client.feb_13.GroupSummaryDemo.GroupSummaryCustomizer::getGroupSummary([Lcom/smartgwt/client/data/Record;Lcom/smartgwt/client/widgets/grid/ListGridField;Lcom/smartgwt/client/widgets/grid/GroupNode;)(recordsJ,fieldJ,groupNodeJ);
                          	           var resultJS = result == null ? null : @com.smartgwt.client.util.JSOHelper::convertToJavaScriptArray([Ljava/lang/Object;)(result);
                          	           return resultJS;
                          	       }));
                          	   }-*/;
                          	}
                          
                          	@Override
                          	public void onModuleLoad() {
                          		
                          		// Create a ListGrid to show the group summary info
                          		final ListGrid testGrid = new ListGrid();
                          		testGrid.setWidth(600);
                          		testGrid.setHeight(224);
                          		testGrid.setCanGroupBy(true);
                          		testGrid.setShowGroupSummary(true);
                          		
                          		
                          		// subset of fields to display
                          		ListGridField countryName = new ListGridField("countryName");
                          		SummaryEnabledField govt = new SummaryEnabledField();
                          		govt.setName("government");
                          		
                          		govt.setWidth(350);
                          		govt.setGroupSummaryCustomizer(new GroupSummaryCustomizer() {
                          			
                          			@Override
                          			public Object[] getGroupSummary(Record[] records,
                          					ListGridField field, GroupNode groupNode) 
                          			{
                          				if (groupNode == null || records == null || records.length == 0) return null;
                          			
                          				String currentGroup = groupNode.getAttribute("groupName");
                          				String[] gridGroups = testGrid.getGroupByFields();
                          				String result = "Totals(";
                          				for (int i = 0; i < gridGroups.length; i++) {
                          					
                          					if (gridGroups[i].equals(currentGroup)) {
                          	                    result += currentGroup + "[" + groupNode.getGroupValue() + "]):";
                          	                    break;
                          	                } else {
                          	                    // Look directly at a record - they should all match
                          	                    // Note that if you had custom 'getGroupValue()' on a field, you
                          	                    // should technically call that here too.
                          	                    String groupValue = records[0].getAttribute(gridGroups[i]);
                          	                    result += gridGroups[i] + "[" + groupValue + "] - ";
                          	                }
                          	            }
                          	            // Returns a single value since we only want to show one
                          				// group summary line
                          	            return new String[] {result};
                          			}
                          		});
                          		ListGridField continent = new ListGridField("continent");
                          		continent.setSummaryFunction(SummaryFunctionType.COUNT);
                          		
                          		testGrid.setFields(countryName, govt, continent);
                          		testGrid.setGroupByField("continent", "countryName");
                          		
                          		
                          		// inline data for speed
                          		testGrid.setData(new ListGridRecord[] {
                          				new ListGridRecord() {{
                          					setAttribute("countryName", "United States");
                          					setAttribute("continent", "North America");
                          					setAttribute("government", "Federal Republic");
                          				}},
                          				new ListGridRecord() {{
                          					setAttribute("countryName", "United Kingdom");
                          					setAttribute("continent", "Europe");
                          					setAttribute("government", "Constitutional Monarchy");
                          				}},
                          				new ListGridRecord() {{
                          					setAttribute("countryName", "Canada");
                          					setAttribute("continent", "North America");
                          					setAttribute("government", "Constitutional Monarchy");
                          				}},
                          				new ListGridRecord() {{
                          					setAttribute("countryName", "China");
                          					setAttribute("continent", "Asia");
                          					setAttribute("government", "Communist State");
                          				}}
                          		});
                          		
                          		testGrid.draw();
                          	}
                          
                          }

                          Comment

                          Working...
                          X