I have a data model that looks like this:
myData = [{
"ListName": "list1",
"domain\\UserA": true,
"UserB": true,
"userC": true
}, {
"ListName": "list2",
"domain\\UserA": true,
"UserB": true,
"userC": true
}];
and I am trying to bind in to a ui-grid like this:
$scope.gridOpts = {
data: myData,
columnDefs: [{
field: "ListName",
displayName: 'listName'
},
{
field: "domain\\UserA",
displayName: 'UserA',
cellTemplate: "<div class='ui-grid-cell-contents'><input type='checkbox' ng-checked='{{COL_FIELD CUSTOM_FILTERS}}' /></div>",
},
{
field: "UserB",
displayName: 'UserB',
cellTemplate: "<div class='ui-grid-cell-contents'><input type='checkbox' ng-checked='{{COL_FIELD CUSTOM_FILTERS}}' /></div>",
}
The user without the backslash works just fine, but I cannot bind the user with the embedded baskslash. How do I resolve this?
Plunkr is here : http://plnkr.co/edit/y61beZ4F8aKpHj83J9jx?p=preview
It is because (two slashes) "\" in the field gets resolved to (one slash) "\" while ui grid internally creates map based on the field name in the column definition provided. So if you are getting 2 slashes in the data's field name (i.e in the bound object's key) then update your column Def to have double slashes to match each slash in the key name. This will enable the internal field mapping with the key name in the data in sync
In your case change def to:-
columnDefs: [{
field: "ListName",
displayName: 'listName'
},{
field: "domain\\\\UserA", //<-- 4 slashes here to match 2 slash in the bound data's key
displayName: 'UserA',
cellTemplate: "<div class='ui-grid-cell-contents'><input type='checkbox' ng-checked='{{COL_FIELD CUSTOM_FILTERS}}' /></div>",
},
angular.module('app', ['ui.grid']).controller('ctrl', function($scope) {
var myData = [{
"ListName": "list1",
"domain\\UserA": true,
"UserB": true,
"userC": true
}, {
"ListName": "list2",
"domain\\UserA": true,
"UserB": true,
"userC": true
}];;
$scope.gridOpts = {
data: myData,
columnDefs: [{
field: "ListName",
displayName: 'listName'
}, {
field: "domain\\\\UserA",
displayName: 'UserA',
cellTemplate: "<div class='ui-grid-cell-contents'><input type='checkbox' ng-checked='{{COL_FIELD CUSTOM_FILTERS}}' /></div>",
}, {
field: "UserB",
displayName: 'UserB',
cellTemplate: "<div class='ui-grid-cell-contents'><input type='checkbox' ng-checked='{{COL_FIELD CUSTOM_FILTERS}}' /></div>",
}]
};
});
<link rel="stylesheet" href="http://ui-grid.info/release/ui-grid-unstable.min.css" />
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script src="http://ui-grid.info/release/ui-grid-unstable.js"></script>
<div ng-app="app" ng-controller="ctrl">
<div ui-grid="gridOpts"></div>
</div>
Related
I have simple controller:
angular.module('it.works', ['ngResource'])
.controller 'ItWorksCtrl', ($scope, Task) ->
$scope.worksTable = {
data: Task.query(),
columnDefs: [
{ field: "created_at", cellFilter: "date:'dd.MM.yyyy'", displayName: 'Дата создания' },
{ field: "task", cellFilter: "limitTo:300", displayName: 'Описание задачи' },
{ field: "performer", displayName: 'Исполнитель' },
{ field: "task_type", displayName: 'Срочность' },
{ field: "is_orgtechnik_task", displayName: 'Оргтехника', cellTemplate: "<div class='ui-grid-cell-contents'><i class='fa {{ COL_FIELD == true && \"fa-check\" }}'></i></div>" },
{ field: "department", displayName: 'Подразделение' },
{ field: "customer", displayName: 'Заказчик' },
{ field: "customer_telephone", displayName: 'Телефон заказчика' },
{ field: "end_date", displayName: 'Дата окончания', cellFilter: "date:'dd.MM.yyyy'" },
{ field: "task_status", displayName: 'Статус', cellTemplate: "<div class='ui-grid-cell-contents status-{{ COL_FIELD }}'>{{['В процессе выполнения', 'Выполнено', 'Невыполнимо'][COL_FIELD]}}</div>"}
]
}
.factory 'Task', ($resource) ->
$resource('/api/it_works/:id.json')
When in looks like that (it have 10 columns), it looks fine.
But if I add one more column (or double any existing):
{ field: "performer", displayName: 'Исполнитель' },
It becomes look like that:
So, it renders only 4 columns. But why? How to fix it?
i have come with this issue and have solved it.
First, you should add ui-grid-auto-resize to your html:
<div ui-grid="gridOptions" ui-grid-pagination ui-grid-resize-columns ui-grid-auto-resize
ui-grid-selection class="grid"></div>
Then, you should add ui.grid.autoResize to your js:
angular.module('it.works', ['ngResource','ngAnimate', 'ngSanitize', 'ui.grid', 'ui.grid.pagination','ui.grid.autoResize','ui.grid.selection', 'ui.grid.resizeColumns'])
.controller 'ItWorksCtrl', ($scope, Task) ->
$scope.worksTable = {
data: Task.query(),
columnDefs: [
{ field: "created_at", cellFilter: "date:'dd.MM.yyyy'", displayName: 'Дата создания' },
{ field: "task", cellFilter: "limitTo:300", displayName: 'Описание задачи' },
{ field: "performer", displayName: 'Исполнитель' },
{ field: "task_type", displayName: 'Срочность' },
{ field: "is_orgtechnik_task", displayName: 'Оргтехника', cellTemplate: "<div class='ui-grid-cell-contents'><i class='fa {{ COL_FIELD == true && \"fa-check\" }}'></i></div>" },
{ field: "department", displayName: 'Подразделение' },
{ field: "customer", displayName: 'Заказчик' },
{ field: "customer_telephone", displayName: 'Телефон заказчика' },
{ field: "end_date", displayName: 'Дата окончания', cellFilter: "date:'dd.MM.yyyy'" },
{ field: "task_status", displayName: 'Статус', cellTemplate: "<div class='ui-grid-cell-contents status-{{ COL_FIELD }}'>{{['В процессе выполнения', 'Выполнено', 'Невыполнимо'][COL_FIELD]}}</div>"}
]
}
.factory 'Task', ($resource) ->
$resource('/api/it_works/:id.json')
I added two extra columns in in kendo grid which have not data in datasource. I add two textboxes in these two columns using template.Now I want to push the values of these two columns into an angular array oncheckbox checked. I search alot about this in google and in stackoverflow. But did not find any relevant answer for my problem Here is the code for adding template in kendo grid
$scope.qualifySubGridColumns = [
{ template: "<input type='checkbox' class='subCheck checkbox' ng-click='getSelectedRow(dataItem)' />" },
{ field: "subList", template: "<input type='number' ng-minlength='0' ng-init='prefferedUser.subList=0'>", title: "SubList" },
{ field: "level", template: '<input type="number" ng-model="prefferedUser.level" ng-minlength="0" ng-init="prefferedUser.level=0">', title: "Level" },
{ field: "lastName", title: "Last Name" },
{ field: "firstName", title: "First Name" },
{ field: "email", title: "Email" },
{ field: "address1", title: "Address 1" },
{ field: "address2", title: "Address 2" },
{ field: "phone", title: "Phone" }
];
and here I want to fetch these columns. But I have no Idea How can i fetch sublist and level field values in selectedRow Array. Please Experts Help me
$scope.selectedRow = [];
$scope.getSelectedRow = function (data) {
$scope.selectedRow.push({ userId: data.substituteId});
// $scope.selectedRow.push({ userId: data.substituteId, sublist: sublist, level: level });
console.log("mydata", $scope.selectedRow);
};
I'm not sure familiar with anuglar, but I've done this in the past using just kendo.
Here is a simple grid I created with a checkbox on one column, and a text input on another column. The dataSource schema only has an id and a name property. But by adding the data bindings to the template input fields, those properties will be added to the dataSource data item.
<div id="grid"
data-role="grid"
data-columns="[{ field: 'id', title: 'Select', template: '<input type=\'checkbox\' data-bind=\'checked: selected\' />' },
{ field: 'name', title: 'Name' },
{ title: 'Age', template: '<input type=\'number\' data-bind=\'value: age\' />' }]"
data-bind="source: itemsDataSource">
</div>
Then if you dump the dataSource the grid is bound to (itemsDataSource in my instance), the items that you have changed the checkbox, or textbox will have those properties.
See sample running at JSBin
From there, you should be able to pull out the fields you want if the selected field is true etc.
I am not sure but it worked for me...
Html:
<body>
<div kendo-grid k-options="gridOptions" k-ng-delay="gridOptions" k-on-change="selected=data"></div>
</body>
<script id="RowId" type="text/x-kendo-template">
<tr>
<td><input ng-model="dataItem.Name"></td>
</tr>
</script>
Js:
$scope.Array= new kendo.data.ObservableArray([Object,Object]);
$scope.gridOptions = {
dataSource: new kendo.data.DataSource({
pageSize: 20,
data: $scope.Array,
autoSync: true,
schema: {
model: {
id: "Id",
}
}
}),
sortable: true,
resizable: true,
autoSync: true,
scrollable: true,
columns: [
{
field: "Name",
title: "Name",
editable: True,
},
],
rowTemplate: kendo.template($("#RowId").html()),
};
I know how to have a working UI-Bootstrap-Datepicker inside an ng-grid cell's editableCellTemplate.
My Question:
It does not work anymore when I replace the enableCellEdit=true option with enableCellEditOnFocus=true (single-click on cell to edit). Does anyone have an Idea why it breaks and how to fix that?
var editableCellTemplateUsingDatePicker = '<input ng-class="\'colt\' col.index" datepicker-popup="dd.MM.yyyy" datepicker-append-to-body=true is-open="isOpen" ng-model="COL_FIELD" my-input="COL_FIELD"/>';
$scope.gridOptions = {
data: 'myData',
//enableCellEdit: true,
enableCellEditOnFocus: true,
enableCellSelection: true,
enableRowSelection: false,
columnDefs: [{
field: 'name',
displayName: 'Name'
}, {
field:'dateOfBirth',
displayName:'Date of Birth',
editableCellTemplate: editableCellTemplateUsingDatePicker,
cellFilter: 'date:"dd.MM.yyyy"',
}]
};
Plunker
Now, I found another way to get to the desired behaviour of single-click edit with the ui-bootstrap datepicker.
You can add ng-click="editCell()" to your custom cellTemplate to enter edit-mode through single-click of the cell. Here the working setup:
var cellTemplateEditOnClick = '<div class="ngCellText" ng-click="editCell()" ng-class="col.colIndex()"><span ng-cell-text>{{row.getProperty(col.field) CUSTOM_FILTER}}</span></div>';
$scope.gridOptions = {
data: 'myData',
enableCellEdit: true,
enableCellSelection: true,
enableRowSelection: false,
columnDefs: [{
field: 'name',
displayName: 'Name',
cellTemplate: cellTemplateEditOnClick.replace('CUSTOM_FILTER', '')
}, {
field:'dateOfBirth',
displayName:'Date of Birth',
editableCellTemplate: editableCellTemplateUsingDatePicker,
cellTemplate: cellTemplateEditOnClick.replace('CUSTOM_FILTER', '| date:"dd.MM.yyyy"')
}]
};
Plunker
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>
I have a ng-grid built with following JSON
[{"TankName":"Tnk1","UseFuel":"100","UnusedFuel":"200"},
{"TankName":"Tnk2","UseFuel":"150","UnusedFuel":"600"},
{"TankName":"TOTAL","UseFuel":"0","UnusedFuel":"0"}]
I have configured a NG-GRID to dispay. Grid will display as below
below is the Grid-otions
columnDefs: [
{ field: 'TankName', displayName: 'Fuel Tank', enableCellEdit: false,},
{ field: 'UseFuel', displayName: 'Use Fuel', editableCellTemplate: '<input ng-input="COL_FIELD" ng-model="COL_FIELD"/>' },
{ field: 'UnusedFuel', displayName: 'Unused Fuel', editableCellTemplate: '<input ng-input="COL_FIELD" ng-model="COL_FIELD"/>' }
]
I want to put the column totals (Bottom Row) when user edit something on the gird. I have to show them in "TOTAL" row. I cannot use FooterTemplate since its not suiting my need
Below is my code in controller
$scope.$on('ngGridEventEndCellEdit', function (data) {
var totalRow;
angular.forEach(a.gridOptions_all.ngGrid.data, function (row) {
if (row.TankName.toString().toUpperCase() != 'TOTAL') {
totalUseFuel += Number(row.UseFuel);
totalUnUseFuel += Number(row.UnusedFuel);
}
else {totalRow = row;}
});
totalRow.UseFuel= totalUseFuel ;
totalRow.UnusedFuel= totalUnUseFuel ;
});
here a plunker. Could some say whether is there a better option
Regarding the picture you placed in the question I would solve it like this:
columnDefs: [{
field: 'TankName',
displayName: 'Tank',
enableCellEdit: false,
cellEditableCondition: 'newFunc(row);'
}, {
field: 'UseFuel',
displayName: 'Ballast Fuel',
editableCellTemplate: '<input ng-input="COL_FIELD" ng-model="COL_FIELD"/>'
}, {
field: 'UnusedFuel',
displayName: 'Trapped Fuel',
cellEditableCondition: 'row.rowIndex != 2',
editableCellTemplate: '<input ng-input="COL_FIELD" ng-model="COL_FIELD"/>'
}, {
displayName: 'Total',
cellTemplate: '<div>{{getTotal(row.entity.UseFuel,row.entity.UnusedFuel)}}<div>'
}
]
};
$scope.getTotal = function(uf, uuf) {
return Number(uf) + Number(uuf);
}
Note the cellTemplate and the getTotal function.
Look at this Plunker to see this updating while you type.