I am using ui-grid in my web application.
Everything is working fine, the issue is when I refresh the grid data the selection gets removed.
In the Fiddle when I select a row and then hit the refresh the button the ui-grid selection gets removed.
JSFiddle: http://jsfiddle.net/mdawood1991/xyuotpe8/6/
HTML:
<div ng-controller="MyCtrl as controller">
<button ng-click="controller.refreshData()" type="button">
Refresh
</button>
<div ui-grid="controller.assetListGrid" ui-grid-selection></div>
</div>
Controller:
var myApp = angular.module('myApp', ["ui.grid", "ui.grid.selection"]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
myApp.controller("MyCtrl", function($scope) {
var self = this;
$scope.name = 'Superhero';
self.assetListGrid = {};
self.gridOptions = {
enableFiltering: true,
enableGridMenu: true,ang
enableColumnMenus: false,
enableRowSelection: true,
enableSelectAll: false,
multiSelect: false,
enableHorizontalScrollbar: 1,
columnDefs: [{
name: 'assetId'
}, {
name: 'reference',
enableHiding: false,
width: 250,
resizeable: true
}],
onRegisterApi: function(gridApi) {
self.assetGridObject = gridApi;
// register the onRowSelect Function here
//this.assetGridObject.selection.on.rowSelectionChanged(null, function(row) {
// if (row.isSelected)
// });
},
appScopeProvider: self
}
self.initGrid = function() {
self.assetListGrid = self.gridOptions;
self.assetListGrid.data = "controller.gridAssets"
}
self.loadInitData = function() {
self.gridAssets = [{
assetId: 1,
reference: "Dawood"
}, {
assetId: 2,
reference: "Dawood 2"
}, {
assetId: 3,
reference: "Dawood 3"
}, {
assetId: 4,
reference: "Dawood 4"
}, ]
}
self.refreshData = function() {
console.log("Data refresh")
self.gridAssets = [{
assetId: 1,
reference: "Refresh"
}, {
assetId: 2,
reference: "Refresh 2"
}, {
assetId: 3,
reference: "Refresh 3"
}, {
assetId: 4,
reference: "Refresh 4"
}, ]
}
self.initGrid();
self.loadInitData();
});
How do I keep the selection?
Seems like I have found a solution:
What I did was first I put the selected row inside a temporary object, when the row is selected
onRegisterApi: function(gridApi) {
self.assetGridObject = gridApi;
// register the onRowSelect Function here
self.assetGridObject.selection.on.rowSelectionChanged(null, function(row) {
if (row.isSelected) {
self.assetGridObject.grid.appScope.selectedRow = row.entity;
}
});
},
FIDDLE: http://jsfiddle.net/mdawood1991/02dpggyo/2/
Then when the data is refreshed I am checking if a row is selected or not, if it a row is selected I am getting the latest value of that row from the Array of new data, this what the refresh data method looks like now:
self.refreshData = function() {
console.log("Data refresh")
self.gridAssets =
[
{assetId: 1,reference: "Refresh 1"},
{assetId: 2,reference: "Refresh 2"},
{assetId: 3,reference: "Refresh 3"},
{assetId: 4,reference: "Refresh 4"}];
if (self.selectedRow)
{
console.log("Row is selected");
//THIS LINE HERE I THINK IS THE KEY -
self.assetGridObject.grid.modifyRows(self.gridAssets);
// GET THE ROW FROM NEWLY LOADED DATA
var selectedRoww = null;
for (var i = 0; i < self.gridAssets.length; i++)
{
//COMPARING BASED ON MY asseId AS THIS IS THE VALUE THAT WILL NOT CHANGE IN MY GRID - OTHER COLUMS CAN CHANGE
if (self.gridAssets[i].assetId == self.selectedRow.assetId)
{
selectedRoww = self.gridAssets[i];
}
}
// THIS LINE HERE IS SELECTING THE ROW FROM THE GRID
self.assetGridObject.selection.selectRow(selectedRoww);
}
}
Related
I have a uib-tabset with four tabs:
<uib-tabset active="activeForm">
<uib-tab index="0" heading="One"><ng-include src="'one.html'"></ng-include></uib-tab>
<uib-tab index="1" heading="Two"><ng-include src="'two.html'"></ng-include></uib-tab>
<uib-tab index="2" heading="Three"><ng-include src="'three.html'"></ng-include></uib-tab>
<uib-tab index="3" heading="Four"><ng-include src="'four.html'"></ng-include></uib-tab>
</uib-tabset>
it has this controller:
$scope.tabs = [
{ title: 'One', route: 'one' },
{ title: 'Two', route: 'two' },
{ title: 'Three', route: 'three' },
{ title: 'Four', route: 'four' }
];
$scope.go = function(route) {
$state.go(route);
};
Each tab has the same structure. They all contain a UI-GRID, and differ only in the data they contain:
$scope.dataList = [];
$scope.selectedFile = null;
$scope.gridOpts = {
enableFiltering: true,
enableRowSelection: true,
enableRowHeaderSelection: false,
multiSelect: false,
modifierKeysToMultiSelect: false,
noUnselect: false,
columnDefs: [..my fields..],
onRegisterApi: function(gridApi) {
//set gridApi on scope
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope,function(row){
$scope.selectedFile = row.entity;
// Switcher selezione/deselezione
if ($scope.atLeastOneIsSelected === false){
$scope.atLeastOneIsSelected = true;
} else {
$scope.atLeastOneIsSelected = false;
}
});
gridApi.selection.on.rowSelectionChangedBatch($scope,function(rows){
$scope.atLeastOneIsSelected = false;
});
$scope.getFirstData();
}
};
$scope.addGridData = function(datalist) {
$scope.dataList = $scope.dataList.concat(datalist);
$scope.gridOpts.data = $scope.dataList;
};
$scope.getMoreDataAsync = function(firstData) {
if ($scope.cancelPromise) {
$scope.cancelPromise.resolve();
}
$scope.cancelPromise = $q.defer();
TypeOneFileSrv.fileList.get(
{
userId: $scope.$stateParams.userId
}, function(data) {
if (data) {
$scope.addGridData(data);
blockUI.stop();
}
}, function(error) {
if (error) {
toaster.pop('error', 'Error', error);
}
}
);
};
$scope.getFirstData = function() {
blockUI.start('Loading 'ONE' tab...');
$scope.selectedFile = null;
$scope.dataList.length = 0;
$scope.getMoreDataAsync(true);
};
At least, here is the Service which calls the server. As for the Controller, even the Services of the four tab are the same and differ only in the url:
angular.module('app').factory('TypeOneFileSrv', ['$resource', function($resource) {
var typeOne = {
fileList: $resource('url_for_the_first_tab/:userId/?', {
userId: '#userId'
}, {
get: {
method: 'GET',
isArray: true
}
})
};
return typeOne;
}]);
My problem is that, even if I added the blockUI in each tab, when I open the page containing the uib-tabset it seems sometimes it does not load all the data. Because for example I see the first two tabs that have the table populated, but the other two are not populated. Or the first two and the last, and so on.
Please try as shown below.
app.js
Inject ui.grid.autoResize module as shown below.
var appModule = angular.module("app", [
'ui.grid.autoResize'
]);
Html
Use ui-grid-auto-resize directive as shown below.
<div class="grid" ui-grid="vm.yourGridOptions" ui-grid-auto-resize></div>
css
Give a width for your grid as shown below.
.grid {
width: 980px !important;
}
There are 2 grids grid1 grid2.
My requirement is: When I select a row in grid1, grid2 should get refreshed. I am able to fetch the modified data based on the row selection from my service, but I am not able to get it to display on my grid2.
I tried
$scope.grid2 = function () { $scope.gridApi.core.notifyDataChange(uiGridConstants.dataChange.ALL);
$scope.gridApi.core.refresh();}
Both the above are in the RowSelectionChanged event inside the grid1 onRegisterAPI
$scope.gridOptions.onRegisterApi = function (gridApi) {
$scope.gridApi = gridApi;
$timeout(function () {
$scope.gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.value = row.entity.MVE_VEID;
console.log($scope.value);
$scope.contractvalues = contracts.query({ id: $scope.value });
console.log($scope.contractvalues);
$scope.gridoptions2 = function () { $scope.gridApi.core.notifyDataChange(uiGridConstants.dataChange.ALL); $scope.gridApi.core.refresh(); }
$scope.refresh = true;
});
How can I refresh the data in grid2?
Current Code:
contrcontroller.js
<pre>
angular
.module('VendorApp')
.controller('ang_contcontroller', ang_contcontroller);
ang_contcontroller.$inject = ['$scope','contracts'];
function ang_contcontroller($scope, contracts) {
$scope.contractvalues = contracts.query({ id: $scope.value });
$scope.gridoptions2 = {
enableRowHeaderSelection: false,
multiSelect: false,
enableRowSelection: true,
enableSelectAll: true,
enableSorting: true,
enableFiltering: true,
enablePagination: true,
enablePaginationControls: true,
paginationCurrentPage: 1,
paginationPageSize: 100,
maxVisibleColumnCount: 200,
columnDefs: [
{ name: 'CONTRACTID', field: 'MCO_COID' },
{ name: 'NAME', field: 'CO_DESC' },
{ name: 'VENDORID', field: 'MCO_VEID' }
],
data: $scope.contractvalues
};
$scope.gridoptions2.onRegisterApi = function (gridApi) {
$scope.gridApi2 = gridApi;
}
}
vencontroller.js
$scope.gridOptions.onRegisterApi = function (gridApi) {
$scope.gridApi = gridApi;
$timeout(function () {
$scope.gridApi.selection.on.rowSelectionChanged($scope, function (row) {
$scope.value = row.entity.MVE_VEID;
console.log($scope.value);
$scope.contractvalues = contracts.query({ id: $scope.value });
console.log($scope.contractvalues);
$scope.gridoptions2 = {};
$scope.gridoptions2.data = $scope.contractvalues;
//$scope.gridApi2.refresh();
$scope.grid2 = function () {
$scope.gridApi2.core.notifyDataChange(uiGridConstants.dataChange.ALL);
$scope.gridApi2.core.refresh();
};
//$scope.grid2 = function () {
// $scope.gridoptions2 = angular.copy($scope.gridoptions2);
// $scope.gridApi.core.notifyDataChange(uiGridConstants.dataChange.ALL= function () { $scope.gridApi.core.notifyDataChange(uiGridConstants.dataChange.ALL); },$scope.gridApi.core.refresh(); );
// }
//$scope.refresh();
//$scope.gridoptions2 = function () { $scope.gridApi.core.notifyDataChange(uiGridConstants.dataChange.ALL); }
});
});
<code>
If I understand correctly you need to update data for grid2
you wrote that you able to get modified base data say "newData".
Assign this new data to "$scope.gridoptions2.data"
$scope.gridoptions2.data = newData;
I need to know how to implement save and restore state in angularui grid without using any buttons. I need to save the state automatically when ever we do any changes in the grid. We have to auto restore the saved state also. Even if we refresh the page the saved state should be restored
Here's what I figured out. I couldn't find a single event for grid state changes, but It does look like they have individual events for almost everything. Here are a few that i'm using. I just set a break point in the onRegisterApi callback and dug through the gridApi object to find the events. http://plnkr.co/edit/LAMZvOkpx6jsD4CWSz04?p=preview
HTML:
<div ui-grid="gridOptions"
ui-grid-selection
ui-grid-resize-columns
ui-grid-auto-resize
ui-grid-move-columns
ui-grid-grouping
ui-grid-save-state>
</div>
JS:
$scope.gridOptions = {
data: [
{ name: 'Jack', title: 'manager', phone: '123456789', location: 'india'},
{ name: 'Suzy', title: 'developer', phone: '465189798', location: 'usa'},
{ name: 'George', title: 'secretary', phone: '82656517', location: 'japan'},
{ name: 'Michael', title: 'analyst', phone: '31321687', location: 'egypt'},
{ name: 'Sara', title: 'consultant', phone: '59595847', location: 'germany'},
{ name: 'Chris', title: 'engineer', phone: '789456123', location: 'russia'},
{ name: 'Elizabeth', title: 'clerk', phone: '963852741', location: 'china'},
{ name: 'Jane', title: 'intern', phone: '147258369', location: 'australia'},
{ name: 'Bill', title: 'accountant', phone: '951487623', location: 'brazil'}
],
columnDefs: [
{ name: 'name' },
{ name: 'title' },
{ name: 'phone' },
{ name: 'location' }
],
enableGridMenu: true,
enableRowSelection: true,
enableRowHeaderSelection: false,
enableColumnResizing: true,
enableColumnReordering: true,
enableFiltering: true,
onRegisterApi: function(gridApi) {
// Keep a reference to the gridApi.
$scope.gridApi = gridApi;
// Setup events so we're notified when grid state changes.
$scope.gridApi.colMovable.on.columnPositionChanged($scope, saveState);
$scope.gridApi.colResizable.on.columnSizeChanged($scope, saveState);
$scope.gridApi.grouping.on.aggregationChanged($scope, saveState);
$scope.gridApi.grouping.on.groupingChanged($scope, saveState);
$scope.gridApi.core.on.columnVisibilityChanged($scope, saveState);
$scope.gridApi.core.on.filterChanged($scope, saveState);
$scope.gridApi.core.on.sortChanged($scope, saveState);
// Restore previously saved state.
restoreState();
}
};
function saveState() {
var state = $scope.gridApi.saveState.save();
localStorageService.set('gridState', state);
}
function restoreState() {
$timeout(function() {
var state = localStorageService.get('gridState');
if (state) $scope.gridApi.saveState.restore($scope, state);
});
}
Here's a service easy to use with localforage
angular.module('starter.controllers')
.factory('SaveStateGridService', function SaveStateGridService($timeout, $state, $rootScope) {
var self = {
stateName: null,
keyLocalStorage: null,
listener: null,
init: function (gridApi) {
self.stateName = $state.$current.name;
self.keyLocalStorage = 'grid-' + self.stateName;
if (self.keyLocalStorage != null) {
// save the state before we leave
self.listerner = $rootScope.$on('$stateChangeStart',
function (event, toState, toParams, fromState, fromParams, options) {
if (fromState.name === self.stateName) {
var item = gridApi.saveState.save();
localforage.setItem(self.keyLocalStorage, item);
}
self.listerner();
}
);
//restore the state when we load if it exists
localforage.getItem(self.keyLocalStorage, function (err, item) {
if (item != null) {
$timeout(function () {
gridApi.saveState.restore(null, item);
}, 1);
}
});
}
}
};
return self;
});
Controller / Component
$scope.gridOptions.onRegisterApi = function (gridApi) {
SaveStateGridService.init(gridApi);
};
Html
<div
ui-grid="gridOptions"
ui-grid-save-state></div>
it's relatively easy to save the state using Angular $cookies
function saveState() {
var state = $scope.gridApi.saveState.save();
$cookies.put('gridState', JSON.stringify(state));
}
Then, to restore:
$scope.restoreState = function() {
$timeout(function() {
var state = JSON.parse($cookies.get('gridState'));
if (state) {
$scope.gridApi.saveState.restore($scope, state);
}
I couldn't find a single event for grid state changes =>
window.onbeforeunload = function(e) {
$scope.saveState();
};
$scope.restoreState();
in case you want to reset the grid
if(localStorage.getItem("justReset")!="1")
$scope.restoreState();
localStorage.setItem("justReset","0")
If you set the enablePaging options of an ng-grid to true, you enable server-side pagination.
What about client-side one? I could not find any hint on this in the documentation, but I can not imagine that ng-grid does not support client-side paging as well.
Any hint?
I think the example given on the angular page (http://angular-ui.github.io/ng-grid/) actually shows an example of client-side paging. If you look at the data load that is being called by the sample script (http://angular-ui.github.io/ng-grid/jsonFiles/largeLoad.json), you'll see that its not actually doing any server-side paging... it's coming down as one big file.
It might help you!!
The AngularJs code-sample
var app = angular.module('myApp', ['ngGrid']);
app.controller('MyCtrl', function($scope, $http) {
$scope.filterOptions = {
filterText: ""
};
$scope.pagingOptions = {
pageSizes: [25, 50, 100],
pageSize: 25,
totalServerItems: 0,
currentPage: 1
};
$scope.setPagingData = function(data, page, pageSize) {
var pagedData = data.slice((page - 1) * pageSize, page * pageSize);
$scope.myData = pagedData;
$scope.pagingOptions.totalServerItems = data.length;
if (!$scope.$$phase) {
$scope.$apply();
}
};
$scope.getPagedDataAsync = function(pageSize, page) {
setTimeout(function() {
$http.get('json').success(function(largeLoad) {
$scope.setPagingData(largeLoad, page, pageSize);
});
}, 100);
};
$scope.$watch('pagingOptions', function() {
$scope.getPagedDataAsync($scope.pagingOptions.pageSize, $scope.pagingOptions.currentPage, $scope.filterOptions.filterText);
}, true);
$scope.gridOptions = {
data: 'myData',
enablePaging: true,
pagingOptions: $scope.pagingOptions,
showFooter: true
};
$scope.gridOptions.columnDefs = 'gridColumnDefs';
// city loc pop state
$scope.gridColumnDefs = [{
field: "city"
},
{
field: "state"
}, {
field: "pop"
}, {
field: "loc"
}
];
});
The HTML code-sample
<div ng-app="myApp" ng-controller="MyCtrl">
<div class="gridStyle" ng-grid="gridOptions"></div>
</div>
I'm experimenting with AngularJS. I want to show a basic Kendo Grid. I'm trying to do this using pure directives. With that in mind, I've looked at the Kendo UI / Angular JS project (https://github.com/kendo-labs/angular-kendo). Unfortunately, my
index.html:
<div>Products: {{products.length}}</div>
<div kendo-grid k-data-source="products" k-selectable="'row'"
k-pageable='{ "refresh": true, "pageSizes": true }'
k-columns='[
{ "field": "Name", "title": "Name"},
{ "field": "Department", "title": "Department"},
{ "field": "LastShipment", "title": "Last Shipment" }
]'>
</div>
controllers.js
function myController($scope) {
console.log("initializing controller...");
$scope.products = [
{ id:1, name:'Tennis Balls', department:'Sports', lastShipment:'10/01/2013' },
{ id:2, name:'Basket Balls', department:'Sports', lastShipment:'10/02/2013' },
{ id:3, name:'Oil', department:'Auto', lastShipment:'10/01/2013' },
{ id:4, name:'Filters', department:'Auto', lastShipment:'10/01/2013' },
{ id:5, name:'Dresser', department:'Home Furnishings', lastShipment:'10/01/2013' }
];
}
I've verified that I've wired up the controller properly. The activity count shows properly. However, the grid does not appear. I can't figure out what I'm doing incorrectly.
Thank you for your help.
You can also setup a Kendo DataSource as an AngularJS Service using the Factory method and inject this into your Controller to conform to AngularJS best practices and patterns.
Full source code and live demo: http://goo.gl/6Z9jop
Customer.cshtml
#{
ViewBag.Title = "Index";
}
<div>
<h2 ng-cloak>{{title}}</h2>
<div>
<div class="demo-section">
<div class="k-content" style="width: 100%">
<div kendo-grid="grid"
k-sortable="true"
k-pageable="true"
k-filterable="true"
k-editable="'inline'"
k-selectable="true"
k-columns='[
{ field: "CustomerID", title: "ID", width: "75px" },
{ field: "CompanyName", title: "Company"},
{ field: "ContactName", title: "Contact" },
{ field: "ContactTitle", title: "Title" },
{ field: "Address" },
{ field: "City" },
{ field: "PostalCode" },
{ field: "Country" },
{ field: "Phone" },
{ field: "Fax" }]'
>
</div>
<style scoped>
.toolbar { padding: 15px; float: right; }
</style>
</div>
</div>
<script type="text/x-kendo-template" id="toolbar">
<div>
<div class="toolbar">
<button kendo-button ng-click="edit(this)"><span class="k-icon k-i-tick"></span>Edit</button>
<button kendo-button ng-click="destroy(this)"><span class="k-icon k-i-tick"></span>Delete</button>
<button kendo-button ng-click="details(this)"><span class="k-icon k-i-tick"></span>Edit Details</button>
</div>
<div class="toolbar" style="display:none">
<button kendo-button ng-click="save(this)"><span class="k-icon k-i-tick"></span>Save</button>
<button kendo-button ng-click="cancel(this)"><span class="k-icon k-i-tick"></span>Cancel</button>
</div>
</div>
</script>
</div>
</div>
customerController.js
'use strict';
northwindApp.controller('customerController',
function ($scope, $rootScope, $location, customerDataSource)
{
customerDataSource.filter({}); // reset filter on dataSource everytime view is loaded
var onClick = function (event, delegate)
{
var grid = event.grid;
var selectedRow = grid.select();
var dataItem = grid.dataItem(selectedRow);
if (selectedRow.length > 0)
{
delegate(grid, selectedRow, dataItem);
}
else
{
alert("Please select a row.");
}
};
$scope.toolbarTemplate = kendo.template($("#toolbar").html());
$scope.save = function (e)
{
onClick(e, function (grid)
{
grid.saveRow();
$(".toolbar").toggle();
});
};
$scope.cancel = function (e)
{
onClick(e, function (grid)
{
grid.cancelRow();
$(".toolbar").toggle();
});
},
$scope.details = function (e)
{
onClick(e, function (grid, row, dataItem)
{
$location.url('/customer/edit/' + dataItem.CustomerID);
});
},
$scope.edit = function (e)
{
onClick(e, function (grid, row)
{
grid.editRow(row);
$(".toolbar").toggle();
});
},
$scope.destroy = function (e)
{
onClick(e, function (grid, row, dataItem)
{
grid.dataSource.remove(dataItem);
grid.dataSource.sync();
});
},
$scope.onChange = function (e)
{
var grid = e.sender;
$rootScope.lastSelectedDataItem = grid.dataItem(grid.select());
},
$scope.dataSource = customerDataSource;
$scope.onDataBound = function (e)
{
// check if there was a row that was selected
if ($rootScope.lastSelectedDataItem == null)
{
return;
}
var view = this.dataSource.view(); // get all the rows
for (var i = 0; i < view.length; i++)
{
// iterate through rows
if (view[i].CustomerID == $rootScope.lastSelectedDataItem.CustomerID)
{
// find row with the lastSelectedProductd
var grid = e.sender; // get the grid
grid.select(grid.table.find("tr[data-uid='" + view[i].uid + "']")); // set the selected row
break;
}
}
};
});
customerDataSource.js
'use strict';
northwindApp.factory('customerDataSource',
function (customerModel)
{
var crudServiceBaseUrl = "/odata/Customer";
return new kendo.data.DataSource({
type: "odata",
transport: {
read: {
async: false,
url: crudServiceBaseUrl,
dataType: "json"
},
update: {
url: function (data)
{
return crudServiceBaseUrl + "(" + data.CustomerID + ")";
},
type: "put",
dataType: "json"
},
destroy: {
url: function (data)
{
return crudServiceBaseUrl + "(" + data.CustomerID + ")";
},
dataType: "json"
}
},
batch: false,
serverPaging: true,
serverSorting: true,
serverFiltering: true,
pageSize: 10,
schema: {
data: function (data) { return data.value; },
total: function (data) { return data["odata.count"]; },
model: customerModel
},
error: function (e)
{
alert(e.xhr.responseText);
}
});
});
It looks as if the field names are spelled wrong. The following works for me:
<div kendo-grid k-data-source="products" k-selectable="'row'"
k-pageable='{ "pageSize": 2, "refresh": true, "pageSizes": true }'
k-columns='[
{ "field": "name", "title": "Name"},
{ "field": "department", "title": "Department"},
{ "field": "lastShipment", "title": "Last Shipment" }
]'>
</div>
Here is a live demo: http://jsbin.com/odeQAfI/2/edit
To avoid the NaN message in the pager you need to make the products field to be a Kendo DataSource:
function MyController($scope) {
$scope.products = new kendo.data.DataSource({
data: [
{ id:1, name:'Tennis Balls', department:'Sports', lastShipment:'10/01/2013' },
{ id:2, name:'Basket Balls', department:'Sports', lastShipment:'10/02/2013' },
{ id:3, name:'Oil', department:'Auto', lastShipment:'10/01/2013' },
{ id:4, name:'Filters', department:'Auto', lastShipment:'10/01/2013' },
{ id:5, name:'Dresser', department:'Home Furnishings', lastShipment:'10/01/2013' }
],
pageSize: 2
});
}
Here is a live demo: http://jsbin.com/ODElUfO/2/edit