How to refresh ng-grid when griddata has different number of columns from previous displayed griddata
Asked Answered
A

3

16

I do have an application where user selects an option to get grid data from server side and depend upon what option user selects, the number of columns in grid data may vary. I am using Angularjs and ng-grid to display data. The first time, it works fine and it does display correct number of columns (e.g 2 columns). but when user selects other option, which gets 3 columns grid-data, ng-grid still thinks of old columns information and tries to map second 3-cols grid-data in old 2 columns. Since columns info is not available, I cannot use columnDefs in controller. How can I refresh ng-grid columns.
Note: I tried to put code at jsFiddle (http://jsfiddle.net/User888/pwUeX/11/), but somehow, I am not able to run it. My complete code is here.

Also: How can I display row# in ng-grid without sending it from server.

My HTML file:
<!DOCTYPE html>
<html ng-app="myApp">  
    <head lang="en">
        <meta charset="utf-8">
        <title>test </title>  
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.10.1/jquery.min.js"></script>
        <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.6/angular.min.js"></script>
        <script type="text/javascript" src="http://angular-ui.github.io/ng-grid/lib/ng-grid.js"></script>
        <script type="text/javascript" src="gridExample.js"></script>

        <link rel="stylesheet" type="text/css" href="http://angular-ui.github.io/ng-grid/css/ng-grid.css" />
        <link rel="stylesheet" type="text/css" href="css/style.css" />
    </head>
    <body ng-controller="GridExampleCtrl">
    <div>
        Grid Selection:    
        <select ng-model="gridSelectedId">
            <option ng-repeat="gridSel in gridSels" value="{{gridSel.GridSelId}}">{{gridSel.GridSelName}}</option>
        </select>   

        <br/>User selected:  {{gridSelectedId}} <br><hr>    
        <div>
            <button ng-click="display()">Display</button><hr>
            <div class="gridStyle" ng-grid="gridOptions"></div>
        </div>      
    </div> 
   </body>
</html>

My Controller is:

var app = angular.module('myApp', ['ngGrid']);

app.controller('GridExampleCtrl', function ($scope, $http, $timeout) {    

    $scope.myData = [];

    $scope.grid1 = [{name: "grid1a", age: 50},
                    {name: "grid1b", age: 43},
                    {name: "grid1c", age: 50},
                    {name: "grid1d", age: 29},
                    {name: "grid1e", age: 34}];

    $scope.grid2 = [{lastname: "grid2a", age: 50, state:'Idaho'},
                    {lastname: "grid2b", age: 43, state:'NewYork'},
                    {lastname: "grid2c", age: 50, state:'California'},
                    {lastname: "grid2d", age: 29, state:'Arizona'},
                    {lastname: "grid2e", age: 34, state:'Utah'}];

    $scope.gridSels = [
                        {GridSelId : 1, GridSelName : 'Grid 1' },       
                        {GridSelId : 2, GridSelName : 'Grid 2' }
                        ]

     $scope.gridOptions = { 
                data: 'myData',
                enableColumnResize: true,
                showGroupPanel: true,
                //pagingOptions: $scope.pagingOptions
            };

    $scope.display = function(){
        console.log("User selected grid : " + $scope.gridSelectedId);
        if ($scope.gridSelectedId == 1) {
            $scope.myData = $scope.grid1;           
        } else {
            $scope.myData = $scope.grid2;
        }
    };      

});

and css looks like:

.gridStyle {
    border: 1px solid rgb(212,212,212);
    width: 800px; 
    height: 400px;
}
Adinaadine answered 24/6, 2013 at 7:28 Comment(0)
C
8

Though a bug in ng-grid prevents this answer from working well with enableColumnResize: true (changes to columnDefs after a column change will result in invisible data), under basic circumstances you can do something along the lines of

$scope.colDefs = [];

$scope.$watch('myData', function() { 
 $scope.colDefs = [];

 angular.forEach(Object.keys($scope.myData[0]), function(key){
    $scope.colDefs.push({ field: key });
  });
}
);

$scope.gridOptions = {
    data: 'myData',
    columnDefs: 'colDefs',
    enableColumnResize: false,
    showGroupPanel: true
};

Here's a working plunker demonstrating it with your example: http://plnkr.co/edit/w1DLtS

Coastal answered 10/7, 2013 at 20:16 Comment(2)
I would warn that re-creating the colDefs array each time might be pretty resource consuming. Ng-grid performs a lot of spacing calculations each initialization. You might be better served modifying the "visible: true/false" parameter instead.Nag
The key here is that colDefs is in the $scope, that's why mine was not working.Lonlona
B
10

You could also call a method that is supplied in the source code. This may not have been available at the time of the question but I ran into the issue myself. If you're able to target the grid itself you can use something similar to this piece of code

scope.gridOptions.ngGrid.buildColumns();

buildColumns() is the major function and you need to redefine the columnDefs array as brentiumbrent mentioned

Biblical answered 31/12, 2013 at 16:50 Comment(2)
I couldn't get this to work, as at the point of changing my columns the ngGrid property was still null. Could you tell me where you placed that code? I'm guessing you were listening for some kind of event and then kicking it off? Thank you.Supersedure
Yeah that function call was made after the kendo directive could get strapped on. We called that as a result of selecting/deselecting columns from a dropdown list located elsewhere on the page. Sorry for responding to this so late..hadn't realized you posted a comment.Biblical
C
8

Though a bug in ng-grid prevents this answer from working well with enableColumnResize: true (changes to columnDefs after a column change will result in invisible data), under basic circumstances you can do something along the lines of

$scope.colDefs = [];

$scope.$watch('myData', function() { 
 $scope.colDefs = [];

 angular.forEach(Object.keys($scope.myData[0]), function(key){
    $scope.colDefs.push({ field: key });
  });
}
);

$scope.gridOptions = {
    data: 'myData',
    columnDefs: 'colDefs',
    enableColumnResize: false,
    showGroupPanel: true
};

Here's a working plunker demonstrating it with your example: http://plnkr.co/edit/w1DLtS

Coastal answered 10/7, 2013 at 20:16 Comment(2)
I would warn that re-creating the colDefs array each time might be pretty resource consuming. Ng-grid performs a lot of spacing calculations each initialization. You might be better served modifying the "visible: true/false" parameter instead.Nag
The key here is that colDefs is in the $scope, that's why mine was not working.Lonlona
N
0

I also ran into this issue when I tried to make this as service(don't have to setup it by myself all the time I need it).

A piece of my service:

setColumns: function(columnDefs){
  $rootScope.columnDefs = columnDefs;      
  return $rootScope.columnDefs;
}

I give new column names and fields in array (columnDefs) after I assign new columns.

Newsstand answered 25/8, 2014 at 11:16 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.