How to dynamically configure ng-grid - angularjs

I have a view in an angularjs application in which I want to allow the user to select between various differently configured grids. Ideally I would like to bind the value passed to the ng-grid directive to a model variable, as illustrated below. However, although this example renders markup that works when a simple string value is passed to ng-grid (ie. <div class="gridStyle" ng-grid="gridOptions1"></div>, dynamic configuration fails.
var app = angular.module('myApp', ['ngGrid']);
app.controller('MyCtrl', function($scope) {
$scope.option;
$scope.myData = [{name: "Moroni", age: 50},
{name: "Tiancum", age: 43},
{name: "Jacob", age: 27},
{name: "Nephi", age: 29},
{name: "Enos", age: 34}];
$scope.gridOptions1 = { data: 'myData',
columnDefs: [{ field:"name", displayName: "NAME"},
{ field:"age", displayName: "AGE"}],
multiSelect: true };
$scope.gridOptions2 = { data: 'myData',
columnDefs: [{ field:"name", displayName: "Name"},
{ field:"age", displayName: "Age"}],
multiSelect: false };
});
<body ng-controller="MyCtrl">
<label>Show me:</label>
<input type="radio" name="option" ng-model="option" value="gridOptions1">Grid A</input>
<input type="radio" name="option" ng-model="option" value="gridOptions2">Grid B</input>
<div class="gridStyle" ng-grid="{{option}}"></div>
</body>
Can anyone tell me please if there is a way of getting ng-grid to accept a different configuration dynamically, or if there is a workaround to this limitation? Please note that I need to reconfigure multiple properties of the grid, not just the columnDefs and data properties for which I believe there are workarounds.
Plunker: http://plnkr.co/edit/mdXrq6?p=preview

It looks like you can do it if you assign columnDefs to a string of a property on the $scope and then change the array: http://plnkr.co/edit/wuob1M?p=preview;
It is described in this issue raised on ng-grid.
JS:
var app = angular.module('myApp', ['ngGrid']);
app.controller('MyCtrl', function($scope) {
$scope.myData = [{name: "Moroni", age: 50},
{name: "Tiancum", age: 43},
{name: "Jacob", age: 27},
{name: "Nephi", age: 29},
{name: "Enos", age: 34}];
$scope.columnDefs1 = [{ field:"name", displayName: "NAME"},
{ field:"age", displayName: "AGE"}];
$scope.columnDefs2 = [{ field:"name", displayName: "Name"},
{ field:"age", displayName: "Age"}];
$scope.gridOptions = { data: 'myData',
columnDefs: 'columnDefs1',
multiSelect: true };
$scope.switchColumnDefs = function() {
$scope.columnDefs1 = $scope.columnDefs2;
}
});
HTML:
<body ng-controller="MyCtrl">
<label>Show me:</label>
<a ng-click="switchColumnDefs()">Switch Options</a>
<div class="gridStyle" ng-grid="gridOptions"></div>
</body>

Just thought I'd share that if anyone is interested in changing from Single Select to MultiSelect it can be done dynamically like so:
$gridScope.selectionProvider.multi = true / false;

Found a nice solution to this on the angular forum. Essentially, if an array of config objects is maintained, individual elements can be passed to the ng-grid directive as in the markup above. Plunker illustrating solution here: http://plnkr.co/edit/TDGKRo?p=preview
var gridOptions1 = {
data: 'myData',
columnDefs: [
{ field:"name", displayName: "NAME"},
{ field:"age", displayName: "AGE"}],
multiSelect: true,
selectedItems: $scope.selected
};
var gridOptions2 = {
data: 'myData',
columnDefs: [
{ field:"name", displayName: "Name"},
{ field:"age", displayName: "Age"}],
multiSelect: false,
selectedItems: $scope.selected
};
$scope.filterTabs = [{grid: gridOptions1}, {grid: gridOptions2}];
<ol>
<li ng-repeat="tab in filterTabs">
<div class="gridStyle" ng-grid="tab.grid"></div>
</li>
</ol>

Another way to do this is to just stick in something like:
<div ng-grid="gridOptions" ng-if="refresh"></div>
Then just flip refresh to off, update the grid config, then back to on in two different refresh cycles.

It is possible like the plnker that I edited for you: Here
Please notice when I played with it, not all options where live refreshing... But some where as you can see in the example.
Basically the solution is to have $scope variables assigned to the params of gridOptions.

Related

Angular Ng-Grid HeaderRowTemplate sorting and two rows header

I'm developping an app in angular 1.2.20 and using the ng-grid 2.0.11 and
I'm having this problem :
when I'm using the headerRowTemplate attribut I loose the sort functionality of ng-grid. Is there a solution to keep it.
I have a second question, as seen in my first question I'm using the headerRowTemplate of ng-grid and I was wondering if anyone has succeeded in making a two rows header grid with or without the headerRowTemplate attribut.
Thanks in advance
I can't sure your real problem. Maybe you can give a Plunker link.
First, I suppose you don't modify from default template.
It's here. headerRowTemplate.html
Second, I suppose you need a display header row, and original sortable header row,
I can't find it from ng-grid direct support, but this hack it's work.
It's a example:
main.js
// main.js
var app = angular.module('myApp', ['ngGrid']);
app.controller('MyCtrl', function($scope) {
$scope.myData = [{name: "Moroni", age: 50},
{name: "Tiancum", age: 43},
{name: "Jacob", age: 27},
{name: "Nephi", age: 29},
{name: "Enos", age: 34}];
$scope.headerRowHeight = 60;
$scope.gridOptions = {
data: 'myData',
headerRowTemplate: 'myHeaderTemplate.html',
headerRowHeight: $scope.headerRowHeight,
columnDefs: [{field: 'name', displayName: 'Name'}, {field:'age', displayName:'Age'}]
};
});
myHeaderTemplate.html
<div class="ngRow ngHeaderText" ng-style="{height: headerRowHeight / 2}" style="text-align:center">I'm other header row</div>
<div ng-style="{ height: col.headerRowHeight / 2, top: col.headerRowHeight / 2 }" ng-repeat="col in renderedColumns" ng-class="col.colIndex()" class="ngHeaderCell">
<div class="ngVerticalBar" ng-style="{height: col.headerRowHeight / 2}" ng-class="{ ngVerticalBarVisible: !$last }"> </div>
<div ng-header-cell></div>
</div>
Plunker

Angular ng-grid input boxes don't close

I am using the example from here:
http://plnkr.co/edit/hy6Evh?p=preview
My module name is different, but other than that it seems the same as the plnkr example.
(function () {
"use strict";
angular.module("productManagement").controller("PriceListCtrl",
["$scope",
PriceListCtrl]);
function PriceListCtrl($scope) {
$scope.myData = [{ name: "Moroni", age: 50 },
{ name: "Tiancum", age: 43 },
{ name: "Jacob", age: 27 },
{ name: "Nephi", age: 29 },
{ name: "Enos", age: 34 }];
$scope.gridOptions = {
data: 'myData',
enableCellSelection: true,
enableCellEditOnFocus: true,
enableRowSelection: false,
columnDefs: [{ field: 'name', displayName: 'Name', enableCellEdit: false },
{ field: 'age', cellFilter: 'number:2', displayName: 'Age' }]
};
}
}());
But when I put it into my application, the input boxes don't close:
In this image, I clicked into the first age row, then the second, then the third. The open input box should close when I click into the second row.
This works correctly in the plnkr ... but not in my application. Any thoughts as to what could be wrong?
I can't believe that this took SO long to resolve... but I found the answer.
Try this plunk: http://plnkr.co/edit/p4iLdfoYydZ9LKU312zK?p=preview
Then try this plunk: http://plnkr.co/edit/hy6Evh?p=preview
In this first case, when you click on the cells for edit and then click on another cell, the edit boxes don't close.
In the second case, the code works fine.
The ONLY difference is the order of the script tags.
This does not work:
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
This DOES work:
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.0.2/angular.min.js"></script>
Hope this helps others so they don't waste as much time as I did!

Updating selected rows into ng-grid

I am updating the list of selectedItems but the selections (checkboxes) on the UI are not getting updated for the same.
index.html
<body ng-controller="MyCtrl">
<div class="gridStyle" ng-grid="gridOptions"></div>
<h3>Rows selected</h3>
<pre>{{selectedRows}}</pre>
<button ng-click="selectAdam()">Select Adam</button>
</body>
main.js
var app = angular.module('myApp', ['ngGrid']);
app.controller('MyCtrl', function($scope) {
$scope.myData = [{name: "Sam", age: 50},
{name: "Peter", age: 43},
{name: "Jacob", age: 27},
{name: "Scott", age: 29},
{name: "Adam", age: 34}];
$scope.selectedRows = [];
$scope.gridOptions = { data: 'myData',
showSelectionCheckbox: true,
selectedItems: $scope.selectedRows
};
$scope.selectAdam = function() {
$scope.selectedRows.push({name: "Adam", age:34});
}
});
Plunkr for the code
Am I missing something here?
Apparently this is how you do it (based on the example at ngGrid:
$scope.selectAdam = function() {
angular.forEach($scope.myData, function(data, index){
if(data.name == 'Adam' && data.age == 34){
$scope.gridOptions.selectItem(index, true);
}
});
}
Working Plunker: http://plnkr.co/edit/K7b2ElQ1Z5uNAijFk7x4?p=info][1

How to evaluate a filter string programmatically in an Angular expression

I'm trying to evaluate filters programmatically within an Angular expression in a template.
HTML:
<div ng-app="myApp">
<div ng-controller = "MyCtrl">
<div ng-grid="gridOptions" class="gridStyle"></div>
</div>
</div>
JS:
var app = angular.module('myApp', ['ngGrid']);
app.controller('MyCtrl', function ($scope) {
$scope.myData = [{name: "Moroni", age: 50},
{name: "Tiancum", age: 43},
{name: "Jacob", age: 43},
{name: "Nephi", age: 29},
{name: "Enos", age: 34}];
$scope.gridOptions = {
data: 'myData',
columnDefs: [{ field: "name", },
{ field: "age", cellTemplate: '<div><div>{{row.getProperty(col.field) | col.colDef.filter}}</div></div>', cellFilter: 'test' }],
};
});
app.filter('test', function () {
return function (input) {
return input + '!';
};
});
CSS:
.gridStyle {
border: 1px solid rgb(212, 212, 212);
width: 100%;
height: 500px;
}
As you can see, in the cellTemplate for the 'age' column, I'm trying to pass through the cell data through a filter that is in a string in my column definitions (col.colDef.filter).
Is this possible?
I want to do this because I want to use just one template but define a variety of filters on each of the columns.
http://jsfiddle.net/GWha8/2/
How about simply adding test as the filter instead of getting the col's:
{{row.getProperty(col.field) | test}}
Updated jsfiddle.
The gridOption id you should be using is cellFilter (not filter). If you are not doing any other formatting that would require a cellTemplate all you need to do it set $scope.gridOptions.columnDefs[1].cellFilter = 'test' like this:
$scope.gridOptions = {
data: 'myData',
columnDefs: [
{
field: "name"
},
{
field: "age",
cellFilter: 'test'
}
]
};
However, if you are do need to do other changes that will require a cellTemplate then you can just reference your filter by name right in the template (no need to define $scope.gridOptions.columnDefs[1].cellFilter) like this:
$scope.gridOptions = {
data: 'myData',
columnDefs: [
{
field: "name"
},
{
field: "age",
cellTemplate: '<div class="ngCellText" ng-class="col.colIndex()">{{COL_FIELD | test}}</div>''
}
]
};
1) you can fix this in ng grid sources inside ngColumn, and use column cellFilter
if (colDef.cellTemplate && !TEMPLATE_REGEXP.test(colDef.cellTemplate)) {
self.cellTemplate = $.ajax({
type: "GET",
url: colDef.cellTemplate,
async: false
}).responseText;
}
self.cellTemplate = self.cellTemplate.replace(CUSTOM_FILTERS, self.cellFilter ? "|" + self.cellFilter : "");
2) you can create custom function which accept filter and return string
function getTemplateFilter(test){
return '<div><div>{{row.getProperty(col.field) | '+ test +'}}</div></div>'
}

How can I get my ng-grid to re-sort itself?

I have some data displayed in an ng-grid.
Some of this data is displayed nearly immediately after the page loads; other data is slower and we stitch it in once it's received.
In doing this, sorting can break if the grid is set to sort data that isn't there when the first half of the data is rendered in the grid.
Is there a nice way to tell the grid to re-sort itself and preserve multiple columns as well as sort directions once all of the data has been received?
JS
var app = angular.module('myApp', ['ngGrid']);
app.controller('MyCtrl', function ($scope) {
$scope.myData = [{name: "Moroni", age: 50},
{name: "Tiancum", age: 43},
{name: "Jacob", age: 43},
{name: "Nephi", age: 29},
{name: "Enos", age: 34}];
$scope.gridOptions = {
data: 'myData',
columnDefs: [{ field: "name", },
{ field: "age" },
{ field: "state" }],
sortInfo: {
fields: [ 'age', 'state' ],
directions: [ 'asc', 'desc' ]
}
};
var lateData = [
{ name: 'Moroni', state: 'NY' },
{ name: 'Tiancum', state: 'CA' },
{ name: 'Jacob', state: 'PA' },
{ name: 'Nephi', state: 'AK' },
{ name: 'Enos', state: 'MO' }
];
setTimeout(function () {
$scope.myData = _.merge($scope.myData, lateData);
$scope.$digest();
}, 3000);
});
HTML
<div ng-app="myApp">
<div ng-controller = "MyCtrl">
<div ng-grid="gridOptions" class="gridStyle"></div>
</div>
</div>
CSS
.gridStyle {
border: 1px solid rgb(212, 212, 212);
width: 100%;
height: 500px;
}
http://jsfiddle.net/akukucka/4vrQq/
Not sure if this is what you wanted:
$scope.resort= function(){
$scope.gridOptions.sortBy('age');
};
Plunker is here
Since I don't have any of your code you have to find a place where/when to do the sorting for yourself.

Resources