Master-detail kendo ui grid - how to sum by column from details grid and display that sum in master grid column by rows

8 posts, 0 answers
  1. Branimir
    Branimir avatar
    10 posts
    Member since:
    Feb 2016

    Posted 25 Apr 2016 Link to this post

    Hi,

    I am working on master details kendo ui application and I use angular. I am not using hierarchical grid. Master and details grid is separated and it is displayed in different tabStrip. Master grid is displayed within first tabStrip and details grid is displayed within second tabStrip. Also, I use angular service for CRUD.              This is my JSON for master grid:

    [{ "Id": 1, "Date": "24.01.2015", "Description": "descr 1", "documentTypeId": 1 },{ "Id": 2, "Date": "26.01.2015", "Description": "description2", "documentTypeId": 2 },{ "Id": 3, "Date": "22.01.2015", "Description": "description3", "documentTypeId": 3 },{ "Id": 4, "Date": "24.01.2015","Description": "description4", "documentTypeId": 2 },{ "Id": 5, "Date": "29.01.2015", "Description": "description5", "documentTypeId": 4 },{ "Id": 6, "Date": "25.01.2015""Description": "description6", "documentTypeId": 6 }]

    This is my angular service:
    angular.module("app").factory('myService', function ($http) {
      
          return {
              getAll: function (onSuccess, onError) {
                  return $http.get('/Scripts/app/data/json/master/masterGridData.js').success(function (data, status, headers, config) {
                      onSuccess(data);
                  }).error(function (data, status, headers, config) {
                      onError(data);
                  });
              },

              getAllItems: function (onSuccess, onError) {
                  return $http.get('/Scripts/app/data/json/master/detailsGridData.js').success(function (data, status, headers, config) {
                      onSuccess(data);
                  }).error(function (data, status, headers, config) {
                      onError(data);
                  });
              }

      }
    });

    This is my angular controller:
    var app = angular.module("app", ["kendo.directives"]).controller("myController", function ($scope, myService) {
      
    $scope.tabStrip = null;
    $scope.$watch('tabStrip', function () {
        $scope.tabStrip.select(0);
    });
      
    $scope.masterDataSource = new kendo.data.DataSource({
        transport: {
            read: function (options) {
                url = "/Scripts/app/data/json/master/masterGridData.js",
                myService.getAll(function (data) {
                    options.success(data);
                }).error(function (data) {
                    options.error(data);
                })
            }
        },
        schema: {
            model: {
                id: "Id",
                fields: {
                    Id: { type: "number" },
                    Date: { type: "string" },
                    Description: { type: "string" },
                    DocumentTypeId: { type: "number" }
                },

                Amount1: { //here there should be sum value from details grid column Amount1 },

                Amount2: { //here there should be sum value from details grid column Amount2 }

            }
        },
        pageSize: 16
    });
      
    $scope.gridMaster = {
        columns: [
                { field: "Id", width: "70px" },
                { field: "Date", title: "Date", width: "70px" },
                { field: "Description", title: "Description", width: "170px" },
                { field: "DocumentTypeId", hidden: true }
        ],
        dataSource: $scope.masterDataSource,
        selectable: true,
        filterable: true,
        scrollable: true,
        pageable: {
            pageSize: 16,
            pageSizes: ["50", "100", "200", "All"]
        },
        toolbar: [{
            name: "create"
        }],
        change: function () {
            var dataItem = this.dataItem(this.select());
            $scope.id = dataItem.Id;
            $scope.date = dataItem.Date;
            $scope.description = dataItem.Description;
            $scope.documentTypeId = dataItem.DocumentTypeId;
            if (dataItem) {
                    gridDetails.dataSource.filter({ field: "foreignKeyId", value: dataItem.Id, operator: "eq" });
                }
        }
    };


    $scope.detailsDataSource = new kendo.data.DataSource({
            transport: {
                read: function (options) {
                    url = "/Scripts/app/data/json/detail/detailsGridData.js",
                    myService.getAllItems(function (data) {
                        options.success(data);
                    }).error(function (data) {
                        options.error(data);
                    });
                }
            },
            schema: {
                model: {
                    id: "Id",
                    fields: {
                        Id: { type: "number" },
                        foreignKeyId: { type: "number" },
                        DescriptionItem: { type: "string" },
                        Amount1: { type: "number" },
                        Amount2: { type: "number" }
                    }
                }
            },
            pageSize: 10
        });

     

    $scope.gridDetails = {
            columns: [
                { field: "Id", hidden: true },
                { field: "finGeneralLedgerId", hidden: true },
                { field: "DescriptionItem", title: "Description Item", width: "270px" },
                { field: "Amount1", title: "Amount 1", width: "80px", format: "{0:n2}" },
                { field: "Amount2", title: "Amount 2", width: "80px", format: "{0:n2}" }
            ],
            dataSource: $scope.detailsDataSource,
            selectable: true,
            filterable: true,
            scrollable: true,
            pageable: {
                pageSize: 10,
                pageSizes: ["15", "30", "50", "All"]
            },
            toolbar: [{
                name: "createNew",
                template: '<button class=\'k-button\' ng-click=\'buttonAddDetails()\'>Add new item</button>'
            }],
            change: function () {
                var dataItem = this.dataItem(this.select());
                $scope.foreignKeyId = dataItem.foreignKeyId;
                $scope.descriptionItem = dataItem.DescriptionItem;
                $scope.amount1 = dataItem.Amount1;
                $scope.amount2 = dataItem.Amount2;
                $scope.$digest();
            },
            height: 215
        };

    });

    This is JSON for details grid:
    [
        { "Id": 1, "foreignKeyId": 1, "DescriptionItem": "descr 1", "Amount1": 0, "Amount2": 1000.00 },
        { "Id": 2, "foreignKeyId": 1, "DescriptionItem": "descr 2", "Amount1": 900.00, "Amount2": 0 },
        { "Id": 3, "foreignKeyId": 2, "DescriptionItem": "descr 3", "Amount1": 970.00, "Amount2": 0 },
        { "Id": 4, "foreignKeyId": 3, "DescriptionItem": "descr 4", "Amount1": 0, "Amount2": 2000.00 },
        { "Id": 5, "foreignKeyId": 2, "DescriptionItem": "descr 5", "Amount1": 1970.00, "Amount2": 0 },
        { "Id": 6, "foreignKeyId": 2, "DescriptionItem": "descr 6", "Amount1": 0, "Amount2": 2250.00 },
        { "Id": 7, "foreignKeyId": 3, "DescriptionItem": "descr 7", "Amount1": 720.00, "Amount2": 0 },
        { "Id": 8, "foreignKeyId": 2, "DescriptionItem": "descr 8", "Amount1": 2800.00, "Amount2": 0 }
    ]

    When I select some row in masterGrid, I have correspond row(s) in detailsGrid.
    As you can see in JSON for details grid there are "foreignKeyId" that show values from masterDataSource Id. Also, there are "Amount1" and "Amount2" values. My question is how can sum by column "Amount1" and "Amount2" in detailsGrid and display that sum in "Amount1" and "Amount2" column by grid row masterGrid. For example:
    Id = 1 and Id = 2 (from JSON details) have same foreignKeyId value (foreignKeyId = 1) which correspond Id from masterDataSource (Id =1 from JSON master). Sum of Amount1 equals 900.00 and sum of Amount2 equals 1000.00. How to display that sum in first row master grid in column Amount1 and Amount2, respectively.

    Any help really useful. Thanks in advance.

    Regards, Branimir
  2. Nikolay Rusev
    Admin
    Nikolay Rusev avatar
    2289 posts

    Posted 27 Apr 2016 Link to this post

    Hello Branimir,

    You could configure sum aggregate in the DataSource for the fields in question. Thus the DataSource will calculate the aggregates and you could use them to visualize in the footerTemplate for the columns.

    However this aggregates will be available only for the DataSource/Grid to which they are defined. You will not be able to show aggregates calculated in the detail grid in the master one, if I understood your scenario correctly.

    Regards,
    Nikolay Rusev
    Telerik
     
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
     
  3. Branimir
    Branimir avatar
    10 posts
    Member since:
    Feb 2016

    Posted 27 Apr 2016 in reply to Nikolay Rusev Link to this post

    I don't use aggregate and  foother template in this case. I have "expanded" column Amount1 and Amount2 in gridMaster. Also,I have input fields (Amount1 and Amount2) in HTML which should display sum by gridDetails columns (Amount1 and Amount2, respectively) for selected griMaster row.
    HTML for this field looks like:

    <div class="divHeightStyle">
         <label for="amount1" class="labelTextSize">Amount1:</label>
         <input id="amount1" type="number" class="k-textboxField" ng-disabled="true" ng-model="amount1Sum" />
    </div>
    <div class="divHeightStyle">
         <label for="amount2" class="labelTextSize">Amount2:</label>
         <input id="amount2" type="number" class="k-textboxField" ng-disabled="true" ng-model="amount2Sum" />
    </div>

    This HTML fields are disabled and only can display values. What is the best way to display sum calculated by columns Amount1 and Amount 2 from detailsGrid, in these input fields? These input fields refers to selected row gridMaster.

    Regards,
    Branimir
  4. Nikolay Rusev
    Admin
    Nikolay Rusev avatar
    2289 posts

    Posted 28 Apr 2016 Link to this post

    Hello Branimir,

    Here is the workflow, if I understand the app scenario correctly.

    1. Master Grid loads

    2. On user selection detail Grid is supplied with data. Now since the values for Amount1 and Amount2 are available in the detail Grid DataSource you should configure aggregates.

    3. When change event of the detail DataSource happens, all the data is available and aggregates has been calculated. From this event handler you could get the values for the calculated aggregates and populate input elements in question.

    Isn't that what you need?

    Regards,
    Nikolay Rusev
    Telerik
     
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
     
  5. Branimir
    Branimir avatar
    10 posts
    Member since:
    Feb 2016

    Posted 28 Apr 2016 in reply to Nikolay Rusev Link to this post

    Hello Nikolay,

    The structure of design of application is following:
    I have two tabStrips. Within the first tabStrips (which is named Overview) I only have master grid. Within the second tabStrip, which is named Update, on the top-half side I have appropriate fields for inputs/selects/datepickers. Also, within the second tabStrip (on the bottom-half side) I have nested two tabStrips (child tabStrip) and within the first child tabStrip I have details grid. When select second child tabStrip we have appropriate fields for inputs/selects/datepickers. Logic is as follows: When select some row in master grid and click second tabStrip, we have populated fields (input/select/datepicker) from this row (top-half side) and display appropriate row(s) in details grid (bottom-half side). Details grid contain columns Amount1 and Amount2. Sum by columns Amount1 and Amount2 should be displayed in two input fields (in top-half side) which belonging to master grid. Also, these calculate values should be displayed for each row in "extend" columns Amount1 and Amoun2 in master grid. My change event in definition of master grid is used for binding to input/select fields and for binding with details grid (display appropriate rows from details grid). When I want add new record (add new row) in details grid - populate all relevant fields (among other things, input Amount1 and Amount2 fields), or change existing, calculated sum by details grid columns (Amount1, Amount2) should be automatically changed and displayed in two inputs fields, respectively (in top-half side). And I think that change event from master grid can not be helpful in this case, but is necessary for binding to related input/select fields and for binding with details grid (display appropriate rows from details grid, when user some row in master grid).
    Did it help this explanation?

    Regards,
    Branimir

  6. Nikolay Rusev
    Admin
    Nikolay Rusev avatar
    2289 posts

    Posted 03 May 2016 Link to this post

    Hello Branimir,

    ` And I think that change event from master grid can not be helpful in this case, but is necessary for binding to related input/select fields and for binding with details grid (display appropriate rows from details grid, when user some row in master grid).
    Did it help this explanation?`  

    That is not what I meant. If aggregates are defined in the detail Grid's DataSource, you should wait for detail Grid DataSource change event. When it is triggered the aggregates will be already calculated and you can show them in other input controls. Before that they will not be available.

    Regards,
    Nikolay Rusev
    Telerik
     
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
     
  7. Branimir
    Branimir avatar
    10 posts
    Member since:
    Feb 2016

    Posted 03 May 2016 in reply to Nikolay Rusev Link to this post

    Hi Nikolay,
    How can implement that? Can you post some basic example? Thanks in advance.

    Regards,
    Branimir
  8. Nikolay Rusev
    Admin
    Nikolay Rusev avatar
    2289 posts

    Posted 05 May 2016 Link to this post

    Hello Branimir,

    Bellow you'l find an example of the algorithm from my previous post:

    http://dojo.telerik.com/@rusev/EnIXat

    Regards,
    Nikolay Rusev
    Telerik
     
    Join us on our journey to create the world's most complete HTML 5 UI Framework - download Kendo UI now!
     
Back to Top