Using NgMask in a AngularGrid table dynamically - angularjs

I'd like to use NgMask in an angularGrid table to edit fields, but I don't know how.
The information from table cames from PHP and fields change depending on the search.
How could I implement it?
Link to NgMask: http://candreoliveira.github.io/bower_components/angular-mask/examples/index.html#/
The angularGrid code with a example:
var module = angular.module("example", ["angularGrid"]);
module.controller("exampleCtrl", function($scope, $timeout) {
var columnDefs = [
{displayName: "Default String", field: "defaultString", width: 150, editable: true, volatile: true, cellRenderer: cellRenderer, newValueHandler: numberNewValueHandler},
{displayName: "Upper Case Only", field: "upperCaseOnly", width: 150, volatile: true, editable: true, cellRenderer: cellRenderer, newValueHandler: numberNewValueHandler},
{displayName: "Number", field: 'number', width: 150, volatile: true, editable: true, cellRenderer: cellRenderer, newValueHandler: numberNewValueHandler},
{displayName: "Custom With Angular", field: "setAngular", width: 175, editable: true, volatile: true, cellRenderer: cellRenderer, newValueHandler: numberNewValueHandler},
{displayName: "Custom No Angular", field: "setNoAngular", width: 175, cellRenderer: cellRendererLink, cellTemplate: '{{row.entity[col.field]}}'
}];
var data = [
{ID:111, defaultString: 'APPLE', upperCaseOnly: 'APPLE', number: 11, setAngular: 'AAA', setNoAngular: 'AAA'},
{ID:222, defaultString: 'ORANGE', upperCaseOnly: 'ORANGE', number: 22, setAngular: 'BBB', setNoAngular: 'BBB'},
{ID:333, defaultString: 'BANANA', upperCaseOnly: 'BANANA', number: 33, setAngular: 'CCC', setNoAngular: 'CCC'},
{ID:444, defaultString: 'PEAR', upperCaseOnly: 'PEAR', number: 44, setAngular: 'DDD', setNoAngular: 'DDD'}
];
$scope.gridOptions = {
columnDefs: columnDefs,
rowData: data,
enableCellEditOnFocus: true,
enableSorting: true,
enableFilter: true,
};
});
I dont want to use ui-grid or something, just angularGrid and some mask.

You could dynamically create the columnsDef and specify in the editableCellTemplate your required mask.
The code works like this:
Get the data from server
Create fields from data keys
Extend the keys with the mappingObj.
Set mappedData to the scope, so ngGrid updates.
You could probably also add a validation property to your data and use this to create the column definition.
The uppercase mask is not working properly. I don't know what's wrong. If you enter some uppercase chars and then quickly a lowercase char it will be possible to enter.
Please have a look at the demo below or in this plunkr.
// main.js
var app = angular.module('myApp', ['ngGrid', 'ngMask']);
app.controller('MyCtrl', function($scope, $http) {
/*$scope.myData = [{name: "Moroni", age: 50, personalId: '123-234-445'},
{name: "Tiancum", age: 43, personalId: '223-234-445'},
{name: "Jacob", age: 27,personalId: '323-234-445'},
{name: "Nephi", age: 29, personalId: '423-234-445'},
{name: "Enos", age: 34, personalId: '523-234-445'}];
*/
$scope.myData = [];
$scope.colDef = [];
/*
var columnDef = [{ field: 'name', displayName: 'First Name', width: 90 },
{ field: 'age', width:50, cellClass: 'ageCell', headerClass: 'ageHeader',
editableCellTemplate: '<input type="number" ng-class="\'colt\' + col.index" ng-input="COL_FIELD" ng-model="COL_FIELD" />' },
{ field: 'personalId', displayName: 'ID', width: 150, editableCellTemplate: '<input ng-model="COL_FIELD" ng-input="COL_FIELD" mask="255-255-255"/>'}];
*/
$http.jsonp('http://www.mocky.io/v2/559304993c82b23c10eea6a6?callback=JSON_CALLBACK').then(function(response){
//'http://www.mocky.io/v2/5592fc513c82b22510eea699?callback=JSON_CALLBACK').then(function (response){
//$scope.colDef=response.data;//["ColumnName":data.something]
var data = response.data,
keys = [],
curKeys = '',
mappedData,
mappingObject = {
/*
name: {
displayName: 'First Name',
width: 90
},*/
age: {
width: 50,
cellClass: 'ageCell',
headerClass: 'ageHeader',
editableCellTemplate: '<input type="number" ng-class="\'colt\' + col.index" ng-input="COL_FIELD" ng-model="COL_FIELD" />'
},
personalId: {
displayName: 'ID',
width: 150,
editableCellTemplate: '<input ng-model="COL_FIELD" ng-input="COL_FIELD" mask="255-255-255"/>'
},
upperCaseOnly: {
displayName: 'uper case only property',
width: 100,
editableCellTemplate: '<input ng-model="COL_FIELD" ng-input="COL_FIELD" mask="A" repeat="10" limit="false" restrict="reject"/>'
}
};
$scope.myData = data;
data.forEach(function(row, index) {
curKeys = Object.keys(row);
console.log(curKeys);
curKeys.forEach(function(key) {
if (keys.indexOf(key) == -1)
keys.push(key);
});
});
mappedData = keys.map(function(key){
return angular.extend({field: key}, mappingObject[key]);
});
console.log(mappedData);
$scope.colDef = mappedData;
});
$scope.filter = {filterText:''};
$scope.gridOptions = {
data: 'myData',
enableFiltering: true,
filterOptions: $scope.filter,
showFilter: true,
enableCellEditOnFocus: true, //enables the editor on a single click, if you use enableCellEdit: true you would have to doubleclick
columnDefs: 'colDef'//columnDef
};
$scope.showRowCount = function() {
console.log($scope.gridOptions.ngGrid.filteredRows.length);
}
});
/*style.css*/
.gridStyle {
border: 1px solid rgb(212,212,212);
width: 400px;
height: 300px
}
<!DOCTYPE html>
<html ng-app="myApp">
<head lang="en">
<meta charset="utf-8">
<title>Custom Plunker</title>
<link rel="stylesheet" type="text/css" href="http://angular-ui.github.com/ng-grid/css/ng-grid.css" />
<link rel="stylesheet" type="text/css" href="style.css" />
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.8.0/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.1/angular.js"></script>
<script type="text/javascript" src="http://angular-ui.github.com/ng-grid/lib/ng-grid.debug.js"></script>
<script type="text/javascript" src="https://cdn.rawgit.com/candreoliveira/ngMask/master/dist/ngMask.js"></script>
<script type="text/javascript" src="main.js"></script>
</head>
<body ng-controller="MyCtrl">
<input ng-model="filter.filterText"/>
<div class="gridStyle" ng-grid="gridOptions"></div>
currently visible items: {{gridOptions.ngGrid.filteredRows.length}}
</body>
</html>

Related

How can I customize the first row in a table using extjs?

I'm using extjs and I want to customize the first row texts in a table to bold and increase the font size. I didnt find any unique property for rows. Is there any way to customize?
Solution:
You may try to use viewConfig config option of Ext.grid.Panel and Ext.tree.Panel. Below are working examples.
Working example (Grid Panel):
Data: customgrid.json
[
{Id : '1', Name: 'Name 1'},
{Id : '2', Name: 'Name 2'},
{Id : '3', Name: 'Name 3'},
{Id : '4', Name: 'Name 4'},
{Id : '5', Name: 'Name 5'},
{Id : '6', Name: 'Name 6'}
]
CSS: customgrid.css
.grid-firstrow .x-grid-cell {
font-weight: bold;
font-size: 18;
}
Grid: customgrid.html
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-all.css">
<link rel="stylesheet" type="text/css" href="./customgrid.css">
<script type="text/javascript" src="../ext/ext-all-debug.js"></script>
<script type="text/javascript">
Ext.define('testmodel', {
extend: 'Ext.data.Model',
fields: [
{name: 'Id', type: 'string'},
{name: 'Name', type: 'string'}
]
});
Ext.onReady(function(){
Ext.QuickTips.init();
Ext.FocusManager.enable();
Ext.Ajax.timeout = 100 * 1000;
Ext.define('Test.Window', {
extend: 'Ext.window.Window',
closeAction: 'destroy',
border: false,
width: 560,
height: 500,
modal: true,
closable: true,
resizable: false,
layout: 'fit',
loadTestData: function() {
var me = this;
me.store.load();
},
initComponent: function() {
var me = this;
me.callParent(arguments);
me.store = new Ext.data.Store({
autoLoad: false,
proxy: {
url: 'customgrid.json',
type: 'ajax',
reader: {type: 'json'},
writer: {type: 'json'}
},
model: 'testmodel'
});
me.grid = Ext.create('Ext.grid.Panel', {
autoScroll: true,
stripeRows: true,
width: 420,
height: 200,
store: me.store,
columnLines: false,
columns : [
{header : 'Id', sortable : true, width : 50, dataIndex : 'Id'},
{header : 'Name', sortable : true, width : 100, dataIndex : 'Name'}
],
viewConfig: {
getRowClass: function(record, index) {
var css = '';
if (index == 0) {
css = 'grid-firstrow';
} else {
css = '';
}
return css;
}
}
});
me.add(me.grid);
me.loadTestData();
}
});
var win = new Test.Window({
});
win.show();
});
</script>
<title>Test</title>
</head>
<body>
</body>
</html>
Working example (Tree Panel):
CSS: customtree.css
.tree-node .x-grid-cell-inner {
font-weight: bold;
font-size: 18px;
}
Tree: customtree.html
<html>
<head>
<meta http-equiv="X-UA-Compatible" content="IE=edge"/>
<link rel="stylesheet" type="text/css" href="../ext/resources/css/ext-all.css">
<link rel="stylesheet" type="text/css" href="./customtree.css">
<script type="text/javascript" src="../ext/ext-all-debug.js"></script>
<script type="text/javascript">
Ext.onReady(function(){
Ext.QuickTips.init();
Ext.FocusManager.enable();
Ext.Ajax.timeout = 100 * 1000;
Ext.define('Test.Window', {
extend: 'Ext.window.Window',
closeAction: 'destroy',
border: false,
width: 560,
height: 500,
modal: true,
closable: true,
resizable: false,
layout: 'fit',
initComponent: function() {
var me = this;
me.callParent(arguments);
me.store = new Ext.data.TreeStore({
proxy: {
type: 'memory',
reader: {
type: 'json'
}
},
model: 'usersw_model'
});
me.tree = new Ext.tree.Panel({
useArrows: true,
autoScroll: true,
animate: true,
enableDD: false,
width: '100%',
flex: 1,
border: false,
rootVisible: false,
allowChildren: true,
store: me.store,
root: {
expanded: true,
text: 'Ext JS',
draggable: false,
id: 'root'
},
viewConfig: {
getRowClass: function(record, index) {
var css = '';
if (index == 0) {
css = 'tree-node';
} else {
css = '';
}
return css;
}
}
});
me.add(me.tree);
var rootnode = me.tree.getRootNode();
var parent1node = rootnode.appendChild({
text: 'Parent1',
leaf: false
});
parent1node.appendChild({
text: 'Child1',
leaf: true
});
parent1node.appendChild({
text: 'Child2',
leaf: true
});
parent1node.appendChild({
text: 'Child3',
leaf: true
});
var parent2node = rootnode.appendChild({
text: 'Parent2',
leaf: false
});
parent2node.appendChild({
text: 'Child1',
leaf: true
});
parent2node.appendChild({
text: 'Child2',
leaf: true
});
parent2node.appendChild({
text: 'Child3',
leaf: true
});
var parent3node = rootnode.appendChild({
text: 'Parent3',
leaf: false
});
}
});
var win = new Test.Window({
});
win.show();
});
</script>
<title>Test</title>
</head>
<body>
</body>
</html>
You'd use CSS for that:
tr:first-child {
font-weight: bold;
font-size: x-large;
}
or output the first row cells as th instead of td and style it this way:
th {
font-weight: bold;
font-size: x-large;
}

How to pass row.entity inside celleditablecondition in UI-grid?

I am trying to set cellEditableCondition based on content of other cell in same row.
For that how do I pass row.entity to cellEditableCondition?
I tried passing row as arguement to function defined oncellEditableCondition but that row object does not have entity property.
I want something like below:
columnDefs: [{
name: 'column1',
field: 'name',
cellEditableCondition: function(row) {
return row.entity.lastname === 'Adams'
}
}, {
name: 'column2',
field: 'lastname'
}]
This small tweak to your code should do it:
var app = angular.module('app', ['ui.grid', 'ui.grid.edit']);
app.controller('MainCtrl', ['$scope', function($scope) {
$scope.gridOptions = {
columnDefs: [{
name: 'column1',
field: 'name',
cellEditableCondition: function(scope) {
return scope.row.entity.lastname === 'Adams'
}
}, {
name: 'column2',
field: 'lastname'
}],
data: [{name: "Tim", lastname: "Harker"},
{name: "Akash", lastname: "Adams"}]
}
}]);
div[ui-grid] {
height: 130px;
}
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.1/angular.min.js"></script>
<script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.0.2/ui-grid.min.js"></script>
<link rel="stylesheet" href="//cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/4.0.2/ui-grid.min.css" />
<div ng-app="app" ng-controller="MainCtrl">
<div ui-grid="gridOptions" ui-grid-edit>
</div>
</div>
Let me know if you have any other questions. Happy to help further, if needed.

ui-grid Data display issue

I'm using ui-grid with my Cordova application. When I try to populate the ui-grid, sometimes data is displayed on the left like in the picture below:
Any help?
HTML
<div ui-grid="{data: gridOptions, columnDefs: gridColumns, paginationPageSize: 10, enableColumnMenus: false, enableHorizontalScrollbar : 0,
enableVerticalScrollbar : 0}" ui-grid-auto-resize ui-grid-pagination class="grid_transmiss"> </div>
JS
$scope.gridColumns = [{
field: 'ref',
displayName: 'Référence'
}, {
field: 'Emq',
displayName: 'Nombre de plots empilés'
}, {
field: 'charge',
displayName: 'Charge nominale (daN)'
}, {
field: 'fp',
displayName: 'Fréquence propre(Hz)'
}, {
field: 'attenuation',
displayName: 'Atténuation(%)'
}, {
field: 'flechereel',
displayName: 'Flèche réelle statique (mm)'
}, {
name: 'Courbe',
displayName: 'Courbe',
cellTemplate: '<i ng-click="grid.appScope.goToChart()"><img src="img/chart.png" style="width=20px;height:20px" alt="Voir courbe" /></i>'
}];
Try defining your grid in your controller like this:
$scope.gridOptions = {
columnDefs: [
{
field: 'ref', displayName: 'Référence', width: "*"
},
{
field: 'Emq', displayName: 'Nombre de plots empilés', width: "*"
},
{
field: 'charge', width: 110, displayName: 'Charge nominale (daN)'
},
{ field: 'fp', displayName: 'Fréquence propre(Hz)', width: "*"
},
{
field: 'attenuation', displayName: 'Atténuation(%)', width: "*"
},
{
field: 'flechereel', displayName: 'Flèche réelle statique (mm', width: "*"
},
{
field: 'Courbe', displayName: 'Release Courbe', width: "*",
cellTemplate: '<i ng-click="grid.appScope.goToChart()"><img src="img/chart.png" style="width=20px;height:20px" alt="Voir courbe" /></i>'
},
],
showGridFooter: true,
enableFiltering: true,
enableSorting: false,
enableColumnMenus: false,
paginationPageSizes: [100, 120, 140],
paginationPageSize: 100,
enableHorizontalScrollbar: uiGridConstants.scrollbars.NEVER,
enableGridMenu: false,
onRegisterApi: function (gridApi) {
$scope.gridApi = gridApi;
}
};
Then in your HTML:
<div ui-grid="gridOptions" class="grid" ui-grid-pagination ui-grid-exporter ui-grid-auto-resize></div>
Also, make sure you include 'uiGridConstants' in our controller definition like so:
ContractorCtrl.$inject = ['$scope', '$interval', '$window', '$filter', 'uiGridConstants', '$q', '$timeout'];
function ContractorCtrl($scope, $interval, $window, $filter, uiGridConstants, $q, $timeout)
Let me know if this solves your issue.
change your column definition according to below format. It will work.
$scope.gridOptions = {
columnDefs: [
{name:'clumnName', fields: 'DisplayValue', width: '20%'},
{name:'clumnName', fields: 'DisplayValue', width: '20%'},
{name:'clumnName', fields: 'DisplayValue', width: '20%'},
],
data: $scope.DisplayDataSet,
}

Marking modified cell/row $dirty in ui-grid 3.0

I have a plunker that is ALMOST just like it is supposed to be. I have to add one requirement to it and I can't find it in the docs or on google.
The grid is set (to be like Excel) where you can begin to edit and the tab key will move from row to row. I need SOME WAY to mark a cell as $dirty if a change was made.
The requirement is an update button to save the ENTIRE grid if there were any changes (again, he wants it just like Excel).
Here's the plunker.
The issue: double-click an editable cell (name, status, M, T, W, H, F) and the tab key will cycle through the entire grid. If a cell value is changed, I need a way to mark it as dirty!
CODE:
(index.html)
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="lodash.js#*" data-semver="3.10.0" src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/3.10.0/lodash.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-touch.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.4.3/angular-animate.js"></script>
<link href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" />
<script src="http://ui-grid.info/docs/grunt-scripts/csv.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/pdfmake.js"></script>
<script src="http://ui-grid.info/docs/grunt-scripts/vfs_fonts.js"></script>
<script src="http://ui-grid.info/release/ui-grid.js"></script>
<link rel="stylesheet" href="http://ui-grid.info/release/ui-grid.css" type="text/css" />
<link rel="stylesheet" href="main.css" type="text/css" />
</head>
<body>
<div ng-controller="MainCtrl">
<strong>Data Length:</strong>
{{ gridOptions.data.length | number }}
<br />
<strong>Last Cell Edited:</strong>
{{msg.lastCellEdited}}
<br />
<div ui-grid="gridOpts" ui-grid-edit="" ui-grid-cellnav="" class="grid"></div>
</div>
<script src="app.js"></script>
</body>
</html>
(app.js)
var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.edit', 'ui.grid.cellNav']);
app.controller('MainCtrl', ['$scope', '$http', function($scope, $http) {
$scope.$scope = $scope;
$scope.pending_view = true;
$scope.gridOpts = {
enableCellEditOnFocus: true,
enableGridMenu: true
};
var dataset = [{
vote_pending: false,
has_comment: false,
is_stale: false,
is_watched: false,
disbursement_issue: false,
name: "Jon",
status: 1,
M: 9,
T: 9,
W: 9,
H: 9,
F: 4
}, {
vote_pending: true,
has_comment: true,
is_stale: true,
is_watched: true,
disbursement_issue: true,
name: "Robbie",
status: 1,
M: 8,
T: 8,
W: 8,
H: 8,
F: 8
}, {
vote_pending: false,
has_comment: false,
is_stale: true,
is_watched: true,
disbursement_issue: false,
name: "Brad",
status: 1,
M: 8,
T: 8,
W: 8,
H: 8,
F: 8
}, {
vote_pending: false,
has_comment: true,
is_stale: false,
is_watched: false,
disbursement_issue: false,
name: "Paul",
status: 1,
M: 8,
T: 8,
W: 8,
H: 8,
F: 8
}, {
vote_pending: false,
has_comment: true,
is_stale: false,
is_watched: true,
disbursement_issue: false,
name: "Billie",
status: 2,
M: 8,
T: 4,
W: 4,
H: 4,
F: 0
}];
$scope.getTotal=function(a, b, c, d, e) {
return a+b+c+d+e;
};
$scope.gridweek = true;
var sByName = _.sortBy(dataset, 'name');
var sPending = _.sortByAll(dataset, ['is_watched', 'vote_pending', 'has_comment', 'disbursement_issue', 'is_stale']).reverse();
$scope.gridOpts.data = sPending;
$scope.pendingSort = function() {
if($scope.gridOpts.data === sByName) {
$scope.gridOpts.data = sPending;
} else if($scope.gridOpts.data === sPending) {
$scope.gridOpts.data = sByName;
}
};
$scope.gridOpts.columnDefs = [
{
name: 'id',
enableCellEdit: false,
enableColumnMenu: false,
headerCellTemplate: 'pending.hdr.html',
cellTemplate: 'pending.icons.html',
width: '15%'
},
{
name: 'name',
enableCellEdit: true,
displayName: 'Name',
cellClass: 'text-left cBlue',
headerCellClass: 'text-center bGreen',
enableColumnMenu: false,
width: '12%'
},
{
name: 'status',
enableCellEdit: true,
displayName: 'Status',
editableCellTemplate: 'ui-grid/dropdownEditor',
enableColumnMenu: false,
cellClass: 'text-left cBlue',
cellFilter: 'mapStatus',
headerCellClass: 'text-center bGreen',
editDropdownValueLabel: 'status',
editDropdownOptionsArray: [
{
id: 1,
status: 'FT'
},
{
id: 2,
status: 'PT'
}
],
visible: $scope.gridweek,
width: '14%'
},
{
name: 'M',
enableCellEdit: true,
displayName: 'M',
enableColumnMenu: false,
type: 'number',
cellFilter: 'number:1',
cellClass: 'text-right cBlue',
headerCellClass: 'text-center bGreen',
width: '8%'
},
{
name: 'T',
enableCellEdit: true,
displayName: 'T',
enableColumnMenu: false,
type: 'number',
cellFilter: 'number:1',
cellClass: 'text-right cBlue',
headerCellClass: 'text-center bGreen',
width: '8%'
},
{
name: 'W',
enableCellEdit: true,
displayName: 'W',
enableColumnMenu: false,
type: 'number',
cellFilter: 'number:1',
cellClass: 'text-right cBlue',
headerCellClass: 'text-center bGreen',
width: '8%'
},
{
name: 'H',
enableCellEdit: true,
displayName: 'H',
enableColumnMenu: false,
type: 'number',
cellFilter: 'number:1',
cellClass: 'text-right cBlue',
headerCellClass: 'text-center bGreen',
width: '8%'
},
{
name: 'F',
enableCellEdit: true,
displayName: 'F',
enableColumnMenu: false,
type: 'number',
cellFilter: 'number:1',
cellClass: 'text-right cBlue',
headerCellClass: 'text-center bGreen',
width: '8%'
},
{
field: 'total',
enableCellEdit: false,
displayName: 'Total',
enableColumnMenu: false,
type: 'number',
cellFilter: 'number:1',
cellClass: 'text-right',
headerCellClass: 'text-center bGreen',
cellTemplate: 'total.tmpl.html',
width: '10%'
}
];
$scope.msg = {};
$scope.gridOpts.onRegisterApi = function(gridApi) {
//set gridApi on scope
$scope.gridApi = gridApi;
gridApi.edit.on.afterCellEdit($scope, function(rowEntity, colDef, newValue, oldValue) {
$scope.msg.lastCellEdited = 'edited row id:' + rowEntity.id + ' Column:' + colDef.name + ' newValue:' + newValue + ' oldValue:' + oldValue;
$scope.$apply();
});
};
}])
.filter('mapStatus', function() {
var statusHash = {
1: 'Full Time',
2: 'Part Time'
};
return function(input) {
if (!input) {
return '';
} else {
return statusHash[input];
}
};
});
I create a dirty flag on scope:
$scope.dirty = false;
and I update the function what monitors editions:
gridApi.edit.on.afterCellEdit($scope, function(rowEntity, colDef, newValue, oldValue) {
$scope.$apply(function(scope) {
scope.dirty = true;
});
});
please see on plunkr: http://plnkr.co/edit/bSTXqp7wzLDL74rN3PII?p=preview
Try to adding a thin layer on top of the dataset to track record dirty status.
var records = [];
angular.forEach(dataset, function (rawdata) {
var record = {};
//Track changed attrs,
//keys are the changed properties and
//values are an array of values [origValue, newValue].
record.changedAttrs = {};
//record dirty status
Object.defineProperty(record, 'isDirty', {
get: function () {
return Object.getOwnPropertyNames(record.changedAttrs).length > 0;
}
});
angular.forEach(rawdata, function (value, key) {
Object.defineProperty(record, key, {
get: function () {
return rawdata[key];
},
set: function (value) {
var origValue = record.changedAttrs[key] ?
record.changedAttrs[key][0] : rawdata[key];
if(value !== origValue) {
record.changedAttrs[key] = [origValue, value];
} else {
delete record.changedAttrs[key];
}
rawdata[key] = value;
}
})
});
records.push(record);
});
Here is the plunker. Providing a custom row template and an extra line of css, the row bg color will change to yellow when the row is dirty.
rowTemplate: '<div ng-repeat="(colRenderIndex, col) in colContainer.renderedColumns track by col.uid" ' +
'ui-grid-one-bind-id-grid="rowRenderIndex + \'-\' + col.uid + \'-cell\'" ' +
'class="ui-grid-cell" ng-class="{ \'ui-grid-row-header-cell\': col.isRowHeader , \'row-dirty\': row.entity.isDirty}" ' +
'role="{{col.isRowHeader ? \'rowheader\' : \'gridcell\'}}" ui-grid-cell></div>'
css
.ui-grid-cell.row-dirty {
background-color: yellow !important;
}
In addition to merlins answer.
His css style didn't work for me. What I did is:
.ui-grid-row-dirty div {
background-color: yellow !important;
}
which will set every cells (within the row) bg color to yellow.

Force edit mode for individual rows ui grid 3.0

I have a need to have more than 1 cell editable at a time. I have an edit button per row from a columnDef I added. I would like the edit button to allow as many columns as I want editable based on a condition.
When I set a condition like below, this only checks if this condition is met when I double click the cell.
$scope.gridOptions.cellEditableCondition: function(scope){
scope.row.entity.name = "Jay"
}
Is there any way to invoke the grids 'Edit Mode' on an entire row for all cells that meet the condition?
If you Want to apply condition only on some columns of your grid below is the example:
columnDefs: [
// default
{ field: 'FileName', displayName: 'FileName', enableCellEdit: false, cellTooltip: true },
{ field: 'RootFilePath', displayName: 'RelativePath', cellTooltip: true, enableCellEdit: false },
{ name: 'File Properties', enableFiltering: false, cellTemplate: '<center><div>' + 'View' + '</div></center>' },
{ field: 'IsEditable', displayName: 'Editable/NonEditable', headerTooltip: true, enableCellEdit: false },
{ field: 'HttpPath', displayName: 'HttpPath', enableCellEdit: true, cellTooltip: true },
{ name: 'Generate HttpPath', cellTemplate: '<center><input type="checkbox" ng-model="row.entity.ToGenerateHttpPath", ng-checked="row.entity.ToGenerateHttpPath", ng-click="grid.appScope.generateHttpPath(row.entity.ToGenerateHttpPath,row.entity.HttpPath)"></center>', enableFiltering: false, headerTooltip: true, enableCellEdit: false },
{field: 'TopLevelSchemaComments', displayName: 'Top Level\n Comments', headerTooltip: true, enableFiltering: true, cellTooltip: true,
cellEditableCondition: function ($scope) {
// put your enable-edit code here, using values from $scope.row.entity and/or $scope.col.colDef as you desire
return $scope.row.entity.IsEditable; // in this example, we'll only allow editable rows to be edited
},
},
{ name: 'Remove', enableFiltering: false, cellTemplate: '<div><center><button ng-disabled ="!(row.entity.IsEditable)" class="fa fa-trash-o" ng-click="grid.appScope.Remove(row.entity.XsdSchemaID,row.entity.XbrlLinkbaseID)"></button></center></div>', enableCellEdit: false }, ]
if you want the enitre grid's all the column to follow the same condition then place the condition only in gridOptions before columnDefs. Below is the Example:
$scope.gridOptions1 = {
enableFiltering: true,
data: [],
showGridFooter: true,
enableGridMenu: true,
enableColumnResizing: true,
cellEditableCondition: function ($scope) {
// put your enable-edit code here, using values from $scope.row.entity and/or $scope.col.colDef as you desire
return $scope.row.entity.IsEditable; // in this example, we'll only allow editable rows to be edited
},
columnResize: true,
columnDefs: [
// default
{ field: 'FileName', displayName: 'FileName', cellTooltip: true },
{ field: 'RootFilePath', displayName: 'RelativePath', cellTooltip:true},
{ name: 'File Properties', enableFiltering: false, cellTemplate: '<center><div>' + 'View' + '</div></center>' },
{ field: 'IsEditable', displayName: 'Editable/NonEditable', headerTooltip: true},
{ field: 'HttpPath', displayName: 'HttpPath', cellTooltip: true },
{ name: 'Generate HttpPath', cellTemplate: '<center><input type="checkbox" ng-model="row.entity.ToGenerateHttpPath", ng-checked="row.entity.ToGenerateHttpPath", ng-click="grid.appScope.generateHttpPath(row.entity.ToGenerateHttpPath,row.entity.HttpPath)"></center>', enableFiltering: false, headerTooltip: true, enableCellEdit: false },
{field: 'TopLevelSchemaComments', displayName: 'Top Level\n Comments', headerTooltip: true, enableFiltering: true, cellTooltip: true},
{ name: 'Remove', enableFiltering: false, cellTemplate: '<div><center><button ng-disabled ="!(row.entity.IsEditable)" class="fa fa-trash-o" ng-click="grid.appScope.Remove(row.entity.XsdSchemaID,row.entity.XbrlLinkbaseID)"></button></center></div>', enableCellEdit: false }, ]
}
I've been working on a similar issue, which differs mainly in that rows are editable based on a flag in the data (rather than a stand-alone button as you have). You can see it in action here; here's the code in case that link breaks.
index.html:
<!DOCTYPE html>
<html ng-app="rowLockDemo">
<head>
<meta charset="utf-8" />
<title>Angular UI-Grid row-lock/cell-edit demo</title>
<script>document.write('<base href="' + document.location + '" />');</script>
<script data-require="angular.js#1.2.x" src="https://code.angularjs.org/1.2.28/angular.js" data-semver="1.2.28"></script>
<script src="http://ui-grid.info/release/ui-grid-unstable.js"></script>
<link rel="stylesheet" href="http://ui-grid.info/release/ui-grid-unstable.css" type="text/css">
</head>
<body>
<div ng-controller="MainCtrl">
<div ui-grid="gridOptions" ui-grid-edit ui-grid-cellNav class="grid"></div>
<strong ng-show="msg.lastCellEdited">Last Edit:</strong> {{msg.lastCellEdited}}
</div>
<script src="app.js"></script>
</body>
</html>
app.js:
var app = angular.module('rowLockDemo', ['ui.grid', 'ui.grid.edit', 'ui.grid.cellNav']);
app.controller('MainCtrl', function($scope, $http) {
$scope.msg = {};
$scope.gridOptions = {
enableCellEdit: false, // set all columns to non-editable unless otherwise specified; cellEditableCondition won't override that
enableCellEditOnFocus: true, // set any editable column to allow edit on focus
cellEditableCondition: function($scope) {
// put your enable-edit code here, using values from $scope.row.entity and/or $scope.col.colDef as you desire
return $scope.row.entity.isActive; // in this example, we'll only allow active rows to be edited
}
};
$scope.gridOptions.columnDefs = [
{name: 'isActive', displayName: 'Edit Status', enableColumnMenu: false, cellTemplate: 'cellTemplate_lock.html'}, // displays isActive status as a button and allow toggling it
{name: 'name', enableCellEdit: true}, // editing is enabled for this column, but will be overridden per row by cellEditableCondition
{name: 'company', enableCellEdit: true} // same for this column
];
$scope.gridOptions.onRegisterApi = function(gridApi) {
$scope.gridApi = gridApi;
gridApi.edit.on.afterCellEdit($scope, function(rowEntity, colDef, newValue, oldValue) {
$scope.msg.lastCellEdited = 'ID: ' + rowEntity.id + ', Column: ' + colDef.name + ', New Value: ' + newValue + ', Old Value: ' + oldValue;
$scope.$apply();
});
};
$http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/500_complex.json').success(function(data) {
$scope.gridOptions.data = data;
});
})
cellTemplate_lock.html:
<!--
Button shows current state (locked/unlocked); clicking it toggles the state.
Initial button state is set by retrieved read-only grid data; lock state is not persisted.
-->
<button ng-click="row.entity.isActive = !row.entity.isActive" ng-model="row.entity.isActive" style="{{row.entity.isActive ? 'background-color: lightgreen' : ''}}">
{{ row.entity.isActive ? 'Unlocked' : 'Locked' }}
</button>

Resources