This is my code
var app = angular.module('app', ['ngTouch', 'ui.grid']);
app.controller('MainCtrl', ['$scope', '$http', function ($scope, $http) {
var today = new Date();
$scope.gridOptions = {
enableFiltering: false,
onRegisterApi: function(gridApi){
$scope.gridApi = gridApi;
$scope.gridApi.grid.registerRowsProcessor( $scope.singleFilter, 200 );
},
columnDefs: [
{ field: 'name' },
{ field: 'gender', cellFilter: 'mapGender' },
{ field: 'company' },
{ field: 'email' },
{ field: 'phone' },
{ field: 'age' },
{ field: 'mixedDate' }
]
};
$http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/500_complex.json')
.success(function(data) {
$scope.gridOptions.data = data;
$scope.gridOptions.data[0].age = -5;
data.forEach( function addDates( row, index ){
row.mixedDate = new Date();
row.mixedDate.setDate(today.getDate() + ( index % 14 ) );
row.gender = row.gender==='male' ? '1' : '2';
});
});
$scope.filter = function() {
$scope.gridApi.grid.refresh();
};
$scope.singleFilter = function( renderableRows ){
var matcher = new RegExp($scope.filterValue);
renderableRows.forEach( function( row ) {
var match = false;
[ 'name', 'company', 'email' ].forEach(function( field ){
if ( row.entity[field].match(matcher) ){
match = true;
}
});
if ( !match ){
row.visible = false;
}
});
return renderableRows;
};
}])
.filter('mapGender', function() {
var genderHash = {
1: 'male',
2: 'female'
};
return function(input) {
if (!input){
return '';
} else {
return genderHash[input];
}
};
});
<!doctype html>
<html ng-app="app">
<head>
<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>
<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">
<input ng-model='filterValue'/><button ng-click='filter()'>Filter</button>
<div id="grid1" ui-grid="gridOptions" class="grid"></div>
</div>
<script src="app.js"></script>
</body>
</html>
In the above code first ui-grid structure display then after data will bind to the ui-grid, but i want to display entire grid with structure after loading data.
this is my plunker http://plnkr.co/edit/?p=preview
A popular design is to show loading status when data is not yet loaded, to do so, you could add a dataLoaded flag to control when the grid is ready, set the flag as true in the success callback of $http.get. See the below:
$scope.dataLoaded = false;
$http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/500_complex.json').success(function(data) {
// ...
$scope.dataLoaded = true;
});
and in your template, it could be as:
<div id="grid1" ui-grid="gridOptions" class="grid" ng-show="dataLoaded"></div>
<div ng-hide="dataLoaded">Loading...</div>
Related
I have a simple UI-Grid application that defines a grid like this
<div ui-grid="gridOptions" ui-grid-pagination class="grid clsVendorsGrid" ui-grid-selection ui-grid-exporter right-click="rightClick($event)" context-menu="menuOptions" context-menu-class="custom_class"></div>
And then the right click event is like this
$scope.rightClick = function (event) {
$scope.gridApi.selection.clearSelectedRows();
var element = angular.element(event.toElement);
var id = element[0].parentElement.id;
This was working fine for the past few years. But since last week the event is now always null. What gives ?
I am using angular-ui-grid version 3.2.9
The error I get on right click is
TypeError: Cannot read property 'parentElement' of undefined
at m.$scope.rightClick (administrativeController.js:281)
Appreciate any inputs on this
EDIT:
I am trying to get the ID on right click, I am binding the ID like this
onRegisterApi: function (gridApi) {
$scope.gridApi = gridApi;
//Register this to Capture Selected Item on right click
gridApi.selection.on.rowSelectionChanged($scope,
function (row) {
if (row.isSelected) {
$scope.selectedId = row.entity.iTempId;
$scope.selectedVendor = row.entity.sBusinessnameLegal;
}
});
}
You just need to change event.toElement to event.target:
$scope.rightClick = function (event) {
var element = angular.element(event.target);
var id = element[0].parentElement.id;
...
}
Here is working snippet:
angular.module("ng-context-menu",[]).factory("ContextMenuService",function(){return{element:null,menuElement:null}}).directive("contextMenu",["$document","ContextMenuService",function(e,n){return{restrict:"A",scope:{callback:"&contextMenu",disabled:"&contextMenuDisabled",closeCallback:"&contextMenuClose"},link:function(t,l,c){function o(n,t){t.addClass("open");var l=e[0].documentElement,c=(window.pageXOffset||l.scrollLeft)-(l.clientLeft||0),o=(window.pageYOffset||l.scrollTop)-(l.clientTop||0),u=t[0].scrollWidth,i=t[0].scrollHeight,a=l.clientWidth+c,d=l.clientHeight+o,p=u+n.pageX,s=i+n.pageY,r=Math.max(n.pageX-c,0),f=Math.max(n.pageY-o,0);p>a&&(r-=p-a),s>d&&(f-=s-d),t.css("top",f+"px"),t.css("left",r+"px"),m=!0}function u(e){e.removeClass("open"),m&&t.closeCallback(),m=!1}function i(e){!t.disabled()&&m&&27===e.keyCode&&t.$apply(function(){u(n.menuElement)})}function a(e){t.disabled()||!m||2===e.button&&e.target===n.element||t.$apply(function(){u(n.menuElement)})}var m=!1;l.bind("contextmenu",function(e){t.disabled()||(null!==n.menuElement&&u(n.menuElement),n.menuElement=angular.element(document.getElementById(c.target)),n.element=e.target,e.preventDefault(),e.stopPropagation(),t.$apply(function(){t.callback({$event:e})}),t.$apply(function(){o(e,n.menuElement)}))}),e.bind("keyup",i),e.bind("click",a),e.bind("contextmenu",a),t.$on("$destroy",function(){e.unbind("keyup",i),e.unbind("click",a),e.unbind("contextmenu",a)})}}}]);
var app = angular.module('app', ['ui.grid','ui.grid.selection']);
app.config(['$compileProvider', function ($compileProvider) {
$compileProvider.debugInfoEnabled(false);
}]);
app.controller('MainCtrl', ['$scope', '$interval', function ($scope, $interval) {
var myData = [
{
"firstName": "Cox",
"lastName": "Carney",
"company": "Enormo",
"employed": true,
iTempId: 1,
sBusinessnameLegal:"sBusinessnameLegal1"
},
{
"firstName": "Lorraine",
"lastName": "Wise",
"company": "Comveyer",
"employed": false,
iTempId: 2,
sBusinessnameLegal: "sBusinessnameLegal2"
},
{
"firstName": "Nancy",
"lastName": "Waters",
"company": "Fuelton",
"employed": false,
iTempId: 3,
sBusinessnameLegal: "sBusinessnameLegal3"
}];
$scope.gridOptions = {
data: myData,
enableRowSelection: true,
onRegisterApi: function (gridApi) {
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope,
function (row) {
if (row.isSelected) {
debugger
$scope.selectedId = row.entity.iTempId;
$scope.selectedVendor = row.entity.sBusinessnameLegal;
}
});
}
};
$scope.rightClick = function (event) {
var element = angular.element(event.target);
//get cellId which should look like
//1464688691229-2-uiGrid-0006-cell
var id = element[0].parentElement.id;
var regex = /(\d+)/g
var result = id.match(regex);
var rowIndex = parseInt(result[1]); //extract second numic match
// console.log(id);
//console.log("rowIndex=%d", rowIndex);
$scope.gridApi.selection.selectRowByVisibleIndex(rowIndex);
};
}]);
app.directive('rightClick', function ($parse) {
return function (scope, element, attrs) {
var fn = $parse(attrs.rightClick);
element.bind('contextmenu', function (event) {
scope.$apply(function () {
event.preventDefault();
fn(scope, { $event: event });
});
});
};
});
<!doctype html>
<html ng-app="app">
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.4.5/angular.min.js"></script>
<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="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/3.1.1/ui-grid.min.js"></script>
<script src="ng-context-menu.min.js"></script>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-grid/3.1.1/ui-grid.min.css" type="text/css">
<link rel="stylesheet" href="main.css" type="text/css">
</head>
<body>
<div ng-controller="MainCtrl">
<p>selectedId: {{selectedId}}</p>
<p>selectedVendor: {{selectedVendor}}</p>
<div id="grid1" ui-grid="gridOptions" ui-grid-selection right-click="rightClick($event)" class="grid"></div>
</div>
</body>
</html>
This is my current code:
var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.pagination']);
app.controller('MainCtrl', [
'$scope', '$http', 'uiGridConstants', function($scope, $http, uiGridConstants) {
var paginationOptions = {
pageNumber: 1,
pageSize: 25,
sort: null
};
$scope.gridOptions = {
paginationPageSizes: [25, 50, 75],
paginationPageSize: 25,
useExternalPagination: true,
useExternalSorting: true,
columnDefs: [
{ name: 'name' },
{ name: 'gender', enableSorting: false },
{ name: 'company', enableSorting: false }
],
onRegisterApi: function(gridApi) {
$scope.gridApi = gridApi;
$scope.gridApi.core.on.sortChanged($scope, function(grid, sortColumns) {
if (sortColumns.length == 0) {
paginationOptions.sort = null;
} else {
paginationOptions.sort = sortColumns[0].sort.direction;
}
getPage();
});
gridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) {
paginationOptions.pageNumber = newPage;
paginationOptions.pageSize = pageSize;
getPage();
});
}
};
var getPage = function() {
var url;
switch(paginationOptions.sort) {
case uiGridConstants.ASC:
url = 'https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/100_ASC.json';
break;
case uiGridConstants.DESC:
url = 'https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/100_DESC.json';
break;
default:
url = 'https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/100.json';
break;
}
$http.get(url)
.success(function (data) {
$scope.gridOptions.totalItems = 100;
var firstRow = (paginationOptions.pageNumber - 1) * paginationOptions.pageSize;
$scope.gridOptions.data = data.slice(firstRow, firstRow + paginationOptions.pageSize);
});
};
getPage();
}
]);
.grid {
width: 600px;
}
<!doctype html>
<html ng-app="app">
<head>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular-touch.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.2.26/angular-animate.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">
<div ui-grid="gridOptions" ui-grid-pagination class="grid"></div>
</div>
<script src="app.js"></script>
</body>
</html>
Here is the original plunker link as a reference: http://plnkr.co/edit/unizPGE4JCFxr5e5jQut?p=preview
The result I am getting is displayed in the following image. As you can see the pagination area seems to be "broken", with wrong sizing and alignments.
Why is the pagination so crookedly? What can I do with this?
Well, let me get started.
First, you are using angular 1.2.26 with the release version of ui-grid. While this doesn't seem to trigger any rendering problem, the official page for UI-Grid advertises a compatibility for Angularjs version 1.4.x to 1.6.x. If you open the developer toolbar you can actually see there is a reported error just because of that.
($scope.$applyAsync was added to Angularjs starting on version 1.3.x. Related info here)
I advise you upgrade to a compatible angularjs version to avoid further problem. Since you are also using the $http.success() construct, which was dropped after angularjs 1.4.3 your best bet is to stick to that version.
As for the pager rendering problem, it would seem that the wrong alignment is caused by the page number input box getting a wrong size. I compared your sample with the one on the official UI-Grid homepage and noticed that in your case the input seems to be missing a box-sizing: border-box setting. Because of this the specified height: 26px; attribute won't include the item padding: so, while on the UI-Grid sample the input will be 26 px high including the 5px padding, in your plunker the padding are added to the height, resulting in a 26+5+5 px high input that is obviously higher than any other element on the line.
Based on my observation, the border-box setting on the original sample is coming from bootstrap-flatly.min.css. I didn't find any notice of bootstrap begin an explicit requirement for paging support, but I don't exclude it. Anyway, in your specific case, adding the missing attribute on the input should be enough.
var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.pagination']);
app.controller('MainCtrl', [
'$scope', '$http', 'uiGridConstants', function($scope, $http, uiGridConstants) {
var paginationOptions = {
pageNumber: 1,
pageSize: 25,
sort: null
};
$scope.gridOptions = {
paginationPageSizes: [25, 50, 75],
paginationPageSize: 25,
useExternalPagination: true,
useExternalSorting: true,
columnDefs: [
{ name: 'name' },
{ name: 'gender', enableSorting: false },
{ name: 'company', enableSorting: false }
],
onRegisterApi: function(gridApi) {
$scope.gridApi = gridApi;
$scope.gridApi.core.on.sortChanged($scope, function(grid, sortColumns) {
if (sortColumns.length == 0) {
paginationOptions.sort = null;
} else {
paginationOptions.sort = sortColumns[0].sort.direction;
}
getPage();
});
gridApi.pagination.on.paginationChanged($scope, function (newPage, pageSize) {
paginationOptions.pageNumber = newPage;
paginationOptions.pageSize = pageSize;
getPage();
});
}
};
var getPage = function() {
var url;
switch(paginationOptions.sort) {
case uiGridConstants.ASC:
url = 'https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/100_ASC.json';
break;
case uiGridConstants.DESC:
url = 'https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/100_DESC.json';
break;
default:
url = 'https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/100.json';
break;
}
$http.get(url)
.success(function (data) {
$scope.gridOptions.totalItems = 100;
var firstRow = (paginationOptions.pageNumber - 1) * paginationOptions.pageSize;
$scope.gridOptions.data = data.slice(firstRow, firstRow + paginationOptions.pageSize);
});
};
getPage();
}
]);
.grid {
width: 600px;
}
.ui-grid-pager-control-input{
box-sizing: border-box !important;
}
<!doctype html>
<html ng-app="app">
<head>
<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>
<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">
<div ui-grid="gridOptions" ui-grid-pagination class="grid"></div>
</div>
<script src="app.js"></script>
</body>
</html>
As you can see in the above sample, I switched the referenced angularjs file version to 1.4.3 and I added the following css rule:
.ui-grid-pager-control-input{
box-sizing: border-box !important;
}
This is the result:
still not very nice, but it seems to be identical to the result I am seeing on the official site:
As a final notice, please consider that the pagination api currently seems to be still in early alpha stage (see: http://ui-grid.info/docs/#!/tutorial/214_pagination), so it may not yet fit your need or present mayor bugs.
If you don't need this pagination controls, you can hide this by add enablePaginationControls false in gridOptions.
And can use other components like 'uib-pagination' for external pagination.
Can someone tell me why this plunk will not allow me to move items between the two lists?
I am able to get shared lists to work using the plain RubaXa Sortable library and plain Javascript, but I have not been able to get them to work with Angular and RubaXa/angular-legacy-sortablejs library.
I have read and re-read the docs on the configuration options here and I swear I am doing it correctly.
I have also reviewed the example from the docs (not allowed to link it here due to low rep points) with no success.
I have created two lists and connected them using identical config info:
var ctrl = this;
ctrl.sortableConf = {
group: {
name: 'tags',
pull: true,
put: true
},
sort: true,
animation: 150,
draggable: '.list-group-item',
filter: '.js-remove',
chosenClass: ".sortable-chosen"
};
They both sort just fine internally, I just can't drag an item from one to the other or vice versa.
The documentation is wrong, or I don't know how to properly reference it when not using a partial page instead of an embedded template.
After debugging the options-loading code in sortable.js, I realized that it was not loading the group: block from the ctrl.sortableConf and I was getting stuck with the default values:
After trying a ton of different ways to do this, I stumbled on this example and was able to work it out form there.
Here is a plunk and a copy of the code just in case that goes away:
// create angular app
var tagsApp = angular.module('tagsApp', ['ng-sortable']);
tagsApp.controller('bugTagController', ['$scope', function($scope) {
$scope.tags = [
'Beans',
'Potatoes'
];
$scope.bugTagControllerConfig = {
group: 'tags',
pull: true,
put: true,
sort: true,
animation: 150,
draggable: '.list-group-item',
filter: '.js-remove',
chosenClass: ".sortable-chosen",
accept: function(sourceItemHandleScope, destSortableScope) {
console.log('masterTagController:accept');
return true;
},
onStart: function(evt) {
console.log('masterTagController:onStart');
},
onEnd: function(evt) {
console.log('masterTagController:onEnd');
},
onAdd: function(evt) {
console.log('masterTagController:onAdd');
},
onRemove: function(evt) {
console.log('masterTagController:onAdd');
},
onFilter: function(evt) {
var el = masterTags.closest(evt.item); // get dragged item
el && el.parentNode.removeChild(el);
console.log('masterTagController:onFilter');
},
onSort: function(evt) {
console.log('masterTagController:onSort');
var $item = $(evt.item);
var id = $item.data('id');
if (evt.action === 'add') {
console.log('masterTagController:add');
// put a check to make sure it's unique
// check to see if this node has already been added and prevent it it has
var itemCount = evt.item.parentNode.children.length;
for (var i = 0; i < itemCount; i++) {
var $child = $(evt.item.parentNode.children[i]);
var childId = $child.data('id');
if (childId === id && i !== evt.newIndex) {
console.log('masterTagController:rejectedNewItem');
evt.preventDefault();
return;
}
}
if (evt.newIndex === itemCount - 1) {
Sortable.utils.swap(evt.item.parentNode, evt.newIndex, evt.newIndex - 1);
}
}
}
};
}]);
tagsApp.controller('masterTagController', ['$scope', function($scope) {
$scope.tags = [
'Apples',
'Oranges',
'Comquats',
'Bannanas',
'Pineapples'
];
$scope.masterTagControllerConfig = {
group: 'tags',
pull: true,
put: true,
sort: true,
animation: 150,
draggable: '.list-group-item',
filter: '.js-remove',
chosenClass: ".sortable-chosen",
accept: function(sourceItemHandleScope, destSortableScope) {
console.log('masterTagController:accept');
return true
},
onStart: function(evt) {
console.log('masterTagController:onStart');
},
onEnd: function(evt) {
console.log('masterTagController:onEnd');
},
onAdd: function(evt) {
console.log('masterTagController:onAdd');
},
onRemove: function(evt) {
console.log('masterTagController:onAdd');
},
onFilter: function(evt) {
var el = masterTags.closest(evt.item); // get dragged item
el && el.parentNode.removeChild(el);
console.log('masterTagController:onFilter');
},
onSort: function(evt) {
console.log('masterTagController:onSort');
var $item = $(evt.item);
var id = $item.data('id');
if (evt.action === 'add') {
console.log('masterTagController:add');
// put a check to make sure it's unique
// check to see if this node has already been added and prevent it it has
var itemCount = evt.item.parentNode.children.length;
for (var i = 0; i < itemCount; i++) {
var $child = $(evt.item.parentNode.children[i]);
var childId = $child.data('id');
if (childId === id && i !== evt.newIndex) {
console.log('masterTagController:rejectedNewItem');
evt.preventDefault();
return;
}
}
if (evt.newIndex === itemCount - 1) {
Sortable.utils.swap(evt.item.parentNode, evt.newIndex, evt.newIndex - 1);
}
}
}
};
}]);
And here is the html:
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="style.css">
</head>
<body>
<div ng-app="tagsApp">
<!-- Starting Secondary Tags -->
<div class="col-md-2">
<h2>Tags on this list</h2>
<div class="well" ng-controller="bugTagController">
<ul id="bugTags" class="list-group" ng-sortable="bugTagControllerConfig" ng-model="tags" style="well-lg">
<li class="list-group-item" ng-repeat="tag in tags" ng-sortable-item style="well-lg">
<div ng-sortable-item-handle>{{ tag }}</div>
</li>
</ul>
</div>
</div>
<!-- Ending Secondary Tags -->
<!-- Starting Master Tags -->
<div class="col-md-2">
<h2>Master Tag List</h2>
<div class="well" ng-controller="masterTagController">
<ul id="masterTags" class="list-group" ng-sortable="masterTagControllerConfig" ng-model="tags" style="well-lg">
<li class="list-group-item" ng-repeat="tag in tags" ng-sortable-item style="well-lg">
<div ng-sortable-item-handle>{{ tag }}</div>
</li>
</ul>
</div>
<!-- Ending Master Tags -->
</div>
</div>
<script type="text/javascript" src="https://code.jquery.com/jquery-3.1.0.js" integrity="sha256-slogkvB1K3VOkzAI8QITxV3VzpOnkeNVsKvtkYLMjfk=" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js" integrity="sha384-Tc5IQib027qvyjSMfHjOMaLkfuWVxZxUPnCJA7l2mCWNIpG9mGCD8wGNIcPD7Txa" crossorigin="anonymous"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular-route.js"></script>
<script type="text/javascript" src="https://rubaxa.github.io/Sortable/Sortable.js"></script>
<script type="text/javascript" src="ng-sortable.js"></script>
<script src="script.js"></script>
</body>
</html>
I would like to the ui-grid row select feature to set the value of a column in the clicked row.
I have a column in the DB named omit. I would like that value to equal the state of the selected row, so if the row is selected then omit = 1, if row is not selected then omit = 0. I think I have this part figured out (however I'm always open to better ideas!).
gridApi.selection.on.rowSelectionChanged($scope,function(row){
if(row.isSelected){
row.entity.omit = 1;
}
if(!row.isSelected){
row.entity.omit = 0;
}
// now save to database...
});
gridApi.selection.on.rowSelectionChangedBatch($scope,function(rows){
angular.forEach(rows, function(value, key) {
if(value.isSelected){
value.entity.omit = 1;
}
if(!value.isSelected){
value.entity.omit = 0;
}
// now save to database...
});
});
What I haven't been able to figure out is how the select the row when the grid is first loaded.
So, on the initial load of the grid, how do I select the row if the value of omit is 1?
You can use the gridApi.selection.selectRow method, but you have to wait until the grid has digested the data for it to work. So you either have to set it on an $interval (or after a $timeout) to keep running while the grid digests the data, or you can call gridApi.grid.modifyRows($scope.gridOptions.data) before you call selectRow... to be honest, I'm not sure why you have to call that.
var app = angular.module('app', ['ngTouch', 'ui.grid', 'ui.grid.selection']);
app.controller('gridCtrl', ['$scope', '$http', '$interval', 'uiGridConstants', function ($scope, $http, $interval, uiGridConstants) {
$scope.gridOptions = { enableRowSelection: true, enableRowHeaderSelection: false };
$scope.gridOptions.columnDefs = [
{ name: 'omit' },
{ name: 'id' },
{ name: 'name'},
{ name: 'age', displayName: 'Age (not focusable)', allowCellFocus : false },
{ name: 'address.city' }
];
$scope.gridOptions.multiSelect = false;
$scope.gridOptions.modifierKeysToMultiSelect = false;
$scope.gridOptions.noUnselect = true;
$scope.gridOptions.onRegisterApi = function( gridApi ) {
$scope.gridApi = gridApi;
gridApi.selection.on.rowSelectionChanged($scope,function(row){
if(row.isSelected){
row.entity.omit = 1;
}
if(!row.isSelected){
row.entity.omit = 0;
}
// now save to database...
});
gridApi.selection.on.rowSelectionChangedBatch($scope,function(rows){
angular.forEach(rows, function(value, key) {
if(value.isSelected){
value.entity.omit = 1;
}
if(!value.isSelected){
value.entity.omit = 0;
}
// now save to database...
});
});
};
$scope.toggleRowSelection = function() {
$scope.gridApi.selection.clearSelectedRows();
$scope.gridOptions.enableRowSelection = !$scope.gridOptions.enableRowSelection;
$scope.gridApi.core.notifyDataChange( uiGridConstants.dataChange.OPTIONS);
};
$http.get('https://cdn.rawgit.com/angular-ui/ui-grid.info/gh-pages/data/500_complex.json')
.success(function(data) {
_.forEach(data, function(row) {
row.omit = 0;
});
/* arbitrarily setting the fourth row's omit value to 1*/
data[3].omit = 1;
$scope.gridOptions.data = data;
/* using lodash find method to grab the row with omit === 1 */
/* could also use native JS filter, which returns array rather than object */
var initSelected = _.find($scope.gridOptions.data, function(row) { return row.omit === 1; });
$scope.gridApi.grid.modifyRows($scope.gridOptions.data);
$scope.gridApi.selection.selectRow(initSelected);
/**
* OR:
* $interval( function() {
* $scope.gridApi.selection.selectRow(initSelected);
* }, 0, 1);
*/
});
}]);
<!DOCTYPE html>
<html ng-app="app">
<head>
<script data-require="lodash.js#4.6.1" data-semver="4.6.1" src="https://cdn.jsdelivr.net/lodash/4.6.1/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>
<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="gridCtrl">
<div ui-grid="gridOptions" ui-grid-selection="" class="grid"></div>
</div>
</body>
</html>
So I'm using Handsontable to render a grid. (Yes, I am NOT using the ngHandsontable. I started out with that but ran into problems and so I went with just rendering a Handsontable from an angularjs directive.)
I want one column to hold an anchor tag.
I want the anchor tag to have the angularjs ng-click directive.
Everything renders correctly but the ng-click is not called.
Here is my example.
var APP = angular.module('APP', ['controllers']);
angular.module('controllers',[])
.controller('testController', function ($scope) {
$scope.doNgClick = function() {
alert('ng-click');
// console.log('ng-click');
};
$scope.simple = [
{
test: "<a href='javascript:void(0);' ng-click='doNgClick()'>Test</a>"
// test: "<a ng-click='doNgClick()'>Test</a>"
}
];
});
APP.directive('htable',function($compile) {
var directive = {};
directive.restrict = 'A';
directive.scope = {
data : '='
};
directive.link = function(scope,element,attrs) {
var container = $(element);
// var safeHtmlRenderer = function (instance, td, row, col, prop, value, cellProperties) {
// var escaped = Handsontable.helper.stringify(value);
// td.innerHTML = escaped;
// return td;
// };
var settings = {
data: scope.data,
readOnly: true,
colHeaders: ['Link'],
columns: [
{
data: "test",
renderer: "html",
// renderer: safeHtmlRenderer,
readyOnly: true
}
]
};
var hot = new Handsontable( container[0], settings );
hot.render();
// console.log(element.html());
// $compile(element.contents())(scope);
};//--end of link function
return directive;
});
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="//handsontable.com/dist/handsontable.full.css">
</head>
<body>
<div ng-app="APP">
<div ng-controller="testController">
<div htable data="simple"></div>
</div
</div>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.24/angular.min.js"></script>
<script src="//handsontable.com/dist/handsontable.full.js"></script>
</body>
</html>
After much reading and digging here is my own answer.
//-- With help from the following:
//--
//-- http://stackoverflow.com/questions/18364208/dynamic-binding-of-ng-click
//-- http://weblogs.asp.net/dwahlin/creating-custom-angularjs-directives-part-3-isolate-scope-and-function-parameters
//--
var APP = angular.module('APP', ['controllers']);
angular.module('controllers',[])
.controller('testController', function ($scope) {
$scope.click = function(msg) {
console.log('ctrl_doNgClick: ng-click: msg: '+msg);
};
$scope.simple = [
{
test: "<a href='javascript:void(0);' ng-click='dir_ctrl_click(\"blah1,blah1\")'>Test 1</a>"
},
{
test: "<a href='javascript:void(0);' ng-click='doClick(\"blah2,blah2\")'>Test 2</a>"
},
{
test: "<a href='javascript:void(0);' ng-click='doClick(\"blah3,blah3\")'>Test 3</a>"
}
];
});
APP.directive('htable',function($compile) {
var directive = {};
directive.restrict = 'A';
directive.scope = {
data : '=',
click : '&'
};
directive.controller = function($scope) {
$scope.dir_ctrl_click = function( msg ) {
console.log('controller: dir_ctrl_click: click via the directive controller method');
$scope.click()(msg);
};
};
directive.link = function(scope,element,attrs) {
var container = $(element);
scope.doClick = function(msg) {
console.log('link: doClick: click via the directive link method');
scope.click()(msg);
};
var linkHtmlRenderer = function (instance, td, row, col, prop, value, cellProperties) {
//-- here is the magic that works
//-- the method, in ng-click, must either be defined here in the link method or in the controller method (the example data contains both)
var el = angular.element(td);
el.html($compile(value)(scope));
return el;
};
var settings = {
data: scope.data,
readOnly: true,
colHeaders: ['Link'],
columns: [
{
data : "test",
renderer : linkHtmlRenderer,
readyOnly : true
}
]
};
var hot = new Handsontable( container[0], settings );
// hot.render();
};//--end of link function
return directive;
});
<!DOCTYPE html>
<html>
<head>
<link rel="stylesheet" href="http://handsontable.com/dist/handsontable.full.css">
</head>
<body>
<div ng-app="APP">
<div ng-controller="testController">
<div htable data="simple" click="click"></div>
</div
</div>
<script src="//code.jquery.com/jquery-1.11.1.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.24/angular.min.js"></script>
<script src="http://handsontable.com/dist/handsontable.full.js"></script>
</body>
</html>