Search code examples
kendo-uikendo-gridkendo-ui-grid

Dynamic Kendo grid columns from response data


I have been trying to create a Kendo grid with dynamic column values based on a date item as part of the response data.

The data I have looks like this:

[
    { Date: '01-01-2018', Name: 'Foo', Value: 1000},
    { Date: '02-01-2018', Name: 'Foo', Value: 2000},
    { Date: '03-01-2018', Name: 'Foo', Value: 3000},
    { Date: '01-01-2018', Name: 'Bar', Value: 1400},
    { Date: '02-01-2018', Name: 'Bar', Value: 2000},
    { Date: '03-01-2018', Name: 'Bar', Value: 5000}
]

My intended structure for the grid is the following:

| Name |  Jan | Feb  | Mar  |
|------|------|------|------|
| Foo  | 1000 | 2000 | 3000 |
| Bar  | 1400 | 2000 | 5000 |

I had a look at https://docs.telerik.com/kendo-ui/controls/data-management/grid/how-to/various/create-with-dynamic-columns-and-data-types but it was not quite what I was trying to do and it required that I have the columns sent as part of the response.

I am working with a wrapper for GridOptions that populates the columns through a staticly defined json. Since my columns are dynamic I am having an issue with defining them there.

On top of that, I am unable to pick out the values for the date besides brute forcing through the values and storing all the unique date entries as columns. And if I have them, then how do I match them up with the correct data entry to display the correct value in the grid?


Solution

  • I hope this helps you. I made a dojo for you and pasted the code bellow for the future. I used the possibility of having a callback transport for the read.

    https://dojo.telerik.com/imeNOdUh/2

    <!DOCTYPE html>
    <html>
    <head>
      <meta charset="utf-8">
      <title>Untitled</title>
    
      <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.1.221/styles/kendo.common.min.css">
      <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.1.221/styles/kendo.rtl.min.css">
      <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.1.221/styles/kendo.default.min.css">
      <link rel="stylesheet" href="https://kendo.cdn.telerik.com/2018.1.221/styles/kendo.mobile.all.min.css">
    
      <script src="https://code.jquery.com/jquery-1.12.3.min.js"></script>
      <script src="https://kendo.cdn.telerik.com/2018.1.221/js/angular.min.js"></script>
      <script src="https://kendo.cdn.telerik.com/2018.1.221/js/jszip.min.js"></script>
      <script src="https://kendo.cdn.telerik.com/2018.1.221/js/kendo.all.min.js"></script></head>
    <body>
      <div id="my-grid"></div>
    
      <script>
    
        function fetchData(success, fail) {
            success([
            { Date: '01-01-2018', Name: 'Foo', Value: 1000},
            { Date: '02-01-2018', Name: 'Foo', Value: 2000},
            { Date: '03-01-2018', Name: 'Foo', Value: 3000},
            { Date: '01-01-2018', Name: 'Bar', Value: 1400},
            { Date: '02-01-2018', Name: 'Bar', Value: 2000},
            { Date: '03-01-2018', Name: 'Bar', Value: 5000}
          ]); 
        }    
    
        var $gridElement = $('#my-grid');
        $gridElement.kendoGrid({
            dataSource: {
                transport: {
                read: function(options) {
    
                  fetchData(function(data) {
    
                    // get month names
                    var monthNames = data
                        .map(function(t) {
                        var monthName = kendo.format("{0:MMM}", kendo.parseDate(t.Date, 'MM-dd-yyyy'));
                        return monthName;
                      })
                        .reduce(function(p, t) {
                            if (p.indexOf(t) == -1)
                            p.push(t);
    
                            return p;                        
                      }, []);
    
                    // transform
                    var result = data.reduce(function(p, t) {
                        var monthName = kendo.format("{0:MMM}", kendo.parseDate(t.Date, 'MM-dd-yyyy'));
    
                      var existing = p.filter(function(t2) {
                        return t2.Name == t.Name;
                      });
    
                      if (existing.length) {
                        existing[0][monthName] = t.Value;
                      } else {
                        var n = {
                            Name: t.Name
                        };
                        monthNames.forEach(function(m) {
                          n[m] = 0;
                        });
    
                        n[monthName] = t.Value;
                        p.push(n);
                      }
    
                      return p;
                    }, []);
    
                    options.success(result);
    
                  });
    
    
                }
              }
            }
        });
    
      </script>
    </body>
    </html>