Testing out Angular ui-grid (ng-grid v.3.0). Can not for the life of me find the selected row. I just want to grab the rows or even row ID of row when a user clicks it. Found the top comment here but I think this is outdated: Getting select rows from ng-grid?
Does anyone know where the gridOptions.selectedItems is being stored in 3.0?
Is this what your are looking for ?
http://ui-grid.info/docs/#/tutorial/210_selection
Activate grid selection capabilities with the ui-grid-selection tag (and ui.grid.selection module registration in your app
register gridApi and use gridApi.selection to access getSelectedRows()
In addition to the steps above https://stackoverflow.com/a/26188783/2658127, you might have to invoke it through a ng-click event to get the actual value/object. At least that's how I had it working.
Eg:
$scope.selectRow = function(){
$scope.gridApi.selection.getSelectedRows();
};
And call selectRow() from the template.
This is for anybody who have been confused like I did, considering the fact that ui-grid does not have the best documentation (specially for this select portion).
The easiest approach is:
Register the gridApi by adding this your controller:
$scope.gridOptions.onRegisterApi = function(gridApi) {
$scope.myGridApi = gridApi;
};
Access the array of selected items:
$scope.myGridApi.selection.getSelectedRows();
With grid ui you have to use the selection.on.rowSelectionChanged to update a scope variable that store the selectedItem.
In this way you can use the value in a binding expression.
var SelectController = function($scope) {
...
$scope.selectedItem = null;
$scope.gridOptions = {
data : 'articles',
enableRowSelection : true,
multiSelect : false,
enableRowHeaderSelection : false,
...
};
$scope.gridOptions.onRegisterApi = function(gridApi) {
// set gridApi on scope
this.$scope.gridApi = gridApi;
}.bind(this);
$scope.gridOptions.onRegisterApi = function(gridApi) {
// set gridApi on scope
this.$scope.gridApi = gridApi;
this.$scope.gridApi.selection.on.rowSelectionChanged($scope,
function(row) {
this.$scope.selectedItem = row.entity;
}.bind(this));
}.bind(this);
Use a an array instead of a plain object if you need multiple selection.
Related
I have a custom directive which is very similar to a drop down. Items in the drop down menu are associated with file names of certain videos. A div below the drop down displays a default video file (I have done this via Videoangular).
Whenever I make a selection from the drop down menu, I am changing the default variable containing filename (String) to the one I want. But, the same is not reflected in the div.
My objective is to refresh div containing the video with appropriate video whenever a selection is made from the drop down menu.
This is my controller:
angular.module('myApp',
[
"ngSanitize",
"com.2fdevs.videogular",
"com.2fdevs.videogular.plugins.controls",
"com.2fdevs.videogular.plugins.overlayplay"
]
)
.controller('ctrl',
["$rootScope", "$scope", "$state", "$log", "Restangular",
function ($rootScope, $scope, $state, $log, Restangular) {
'use strict';
var vm = this;
//DEFAULT VIDEO FILE NAME
vm.fields = "WaterCool1";
this.config = {
sources: [
{src: "assets/data/"+vm.fields+".mp4", type: "video/mp4"}
]
};
vm.loadPage = loadPage;
vm.coolingSystemTypeSelector = {coolingSystemTypeSelector:{}};
getAll('cooling-system-type').then(
function(objs) {
$log.debug("get Cooling System Type", objs);
vm.coolingSystemTypeSelector = objs.selector;
vm.fields = "WaterCool1";
vm.coolingSystemTypeSelector.onSelect = function (selection) {
if(!selection){
return;
}
$log.debug("Cooling System Type Selection == ", selection);
if(selection.label==="ACC"){
vm.fields = "AirCool";
}else if(selection.label === "WCC-CT"){
vm.fields = "WaterCool1";
}else if(selection.label === "WCC-DC"){
vm.fields = "WaterCool2";
}
};
}
);
///.....
}
]
);
This is my HTML:
<div>
<selector form="form" columns=vm.columns target="vm.coolingSystemTypeSelector"></selector>
</div>
<hr>
<div id="refreshThisDiv">
<!--I want to refresh this div-->
<videogular vg-theme="vm.config.theme">
<!--VIDEOGULAR CODE-->
</videogular>
</div>
What you need is not to refresh the div. You need angular to refresh the div based on you modifying bound properties.
Your declaration of this.config is actually static and you are never modifying the value of this.config.sources src after instantiation. As that code is running only once it will forever remain as "assets/data/WaterCool1.mp4".
What you need to do instead at least, is to modify this value upon selection of an option in the drop-down. Something like:
// ...
var that = this;
getAll('cooling-system-type').then(
// ... inside onSelect ...
if(selection.label==="ACC") {
that.config.sources = [{src: "assets/data/AirCool.mp4", type: "video/mp4"}];
}
// ...
Even then, with this code, you might need to trigger a manual $apply as angular may not be aware of your change to the field via this onSelect event handling. Ideally you will be able to bind the event to the function directly in HTML by using ng-change and avoid the need for that.
If you provide a full sample (https://plnkr.co/edit/), it's easier to guide you to a solution and explain in without the need to rewrite your original code.
I'm quite new to AngularJS and had to takeover somebody else's project at work which has little to no documentation.
I have 2 kinds of check-boxes in my application, one is a "Select All" checkbox and another is a device selection checkbox. As the name suggests, the select all will select all the devices listed below it and if I uncheck the "select all" checkbox, I can check the devices individually to see them.
Here is the code of the Select all checkbox -
<input type="checkbox" data-ng-model='devCtrl.uiChoices.selectAll' value='true' data-ng-change="devCtrl.selectAll()"/><h4>Select / Deselect All</h4>
Controller:
_this.uiChoices.selectAll = true;
I can understand from above that by default, select all is checked and I can see all the devices below it checked too.
Moving onto the device check-box -
<input type="checkbox" data-ng-model='device.draw' data-ng-change="device = devCtrl.adjustVisibility(device)" />
Controller -
_this.adjustVisibility = function(draw) {
draw.marker.setVisible(draw.plot);
return draw;
}
Basically, whenvever the device is selected, it will appear on a google map. If it is unchecked, it won't appear on the map.
My question is, after I uncheck the "Select all" checkbox and then select only 2 devices in the list below and then do a page refresh, I want the select all to be disabled and show only those 2 devices to be checked and displayed on the map.
The list of devices is being pulled from a MySQL database and is updated dynamically.
Any help is appreciated.
As I said, you can do it by 3 different ways.
1 - Using $scope variable
In AngularJS you have a main Controller usually set at index.HTML body that you can access from all other controllers. You could use it to store your data on the $scope variable. See the example:
index.html:
<body ng-controller="DefaultController">
DefaultController.js:
angular.module('YourModule').controller('DefaultController', ['$scope', function ($scope) {
//Storing Your data
$scope.isChecked = true;
}]);
YourCheckBoxController.js
angular.module('YourModule').controller('YourCheckBoxController', ['$scope', function ($scope) {
//Here you gonna access the $scope variable, that does not change on page reload
$scope.accessingTheVariable= function () {
if ($scope.isChecked) {
//Select All
}
else {
//Do not Select All
}
};
$scope.onCheckBoxToggle {
$scope.isChecked = _this.uiChoices.selectAll;
//More code
};
}]);
2- Using localStorage
//The property exists
if (localStorage.hasOwnProperty("isChecked")) {
if(localStorage.isChecked) {
//Select All
}
else {
//Do not Select All
}
}
//To set localStorage.isChecked
localStorage.setItem("isChecked", _this.uiChoices.selectAll);
3 - Angular Service (Factory)
On this scenario you should create a service that could be accessed from every Controller in your project (usefull if you gonna use the data on more than 1 Controller). Look:
YourService.js
angular.module('YouModule').factory('YouService', function () {
var data =
{
IsChecked = true
};
data.buildIsChecked = function (isChecked) {
this.IsChecked = isChecked;
};
return data;
});
YourIsCheckedController.js:
angular.module('YourModule').controller('YourCheckBoxController',
['$scope', 'YouService', function ($scope, YouService) {
//Setting the service
//...
YouService.buildIsChecked(_this.uiChoices.selectAll);
//Accessing the service Information (it could be accessed from any Controller, just remember to set Service Name at begin of the module declaration)
var isChecked = MenuService.IsChecked;
}]);
You need a way of saving those checked devices.
Try localStorage. Basically, when you select a device, add it to an array, like checkedDevices and add this array to localStorage like so:
localStorage.setItem("devices", JSON.stringify(checkedDevices));
then, at the beginning of your controller, get this array from the localStorage:
var devices = JSON.parse(localStorage.getItem("devices"));
then, check if it has items, if it does, set selectAll to false:
if (devices.length > 0){
this.selectAll = false;
}else{
this.selectAll = true;
}
then, for every device, check if it is in devices array, if it is, select it.
I'm now developing website and there has edit note field features in ng-repeat. To edit note field, user need to click link to display form first then key-in into it and then save it as follow. Problem is i cannot hide that input after successfully saved. Coding is as follow.
index.jade
tr(data-ng-repeat="application in job.applications")
td.notes
div.bold #{getMessage('Notes:')}
div.normal
div(ng-hide='showDetails')
{{application.note}}
.br
a.admin_edit_gray(href='#', ng-click="showDetails = ! showDetails") Edit Note
div(ng-show='showDetails')
textarea.form-control.small-text-font(ng-model='editableTitle', ng-show='showDetails', maxlength="100", ng-trim="false")
div.editable
div(ng-if="editableTitle.length == 100")
| #{getMessage('max 100 symbols.')}
a.small-text-editButton(href='#', ng-click='save(application, editableTitle, application.id)') Save
| |
a.small-text-cancelButton(href='#', ng-click="showDetails = ! showDetails") close
controller.js
$scope.showDetails = false;
$scope.noteFormData = {};
$scope.save = function(application, editableTitle, appId) {
$scope.noteFormData = {
appId: appId,
note: editableTitle
};
mytestService.writeNote($scope.noteFormData).then(
function (notemessage) {
application.note = notemessage;
alert('Note is successfully saved.');
$scope.showDetails = false;
}
);
};
I've tried to hide form as $scope.showDetails = false; after successfully saved. But it does not work at all. Please help me how to solve that issue.
You are creating showDetails inside the $scope of the ngRepeat. Each iteration of the loop creates a new child $scope of the controller's $scope.
In this way, just set $scope.showDetails from the controller will not work.
In order to fix that you need to get the reference to the object that is being iterated and set the show details:
Instead of:
ng-click="showDetails=!showDetails"
Use:
ng-click="application.showDetails=!application.showDetails"
After that, when submiting, you can choose which one you would like to show or hide by using the correct reference or by iterating over all itens of the array and setting showDetails to false.
Instead of:
$scope.showDetails = false;
Use:
application.showDetails = false;
set a variable in controller and set its value false .After your save() function is executed successfully set that variable to true. And in the view page put an condition of ng-show on tr if that value that is true.
I am rendering a component into a grid rowExpander plugin rowBodyTpl:
plugins: [{
ptype: 'rowexpander',
rowBodyTpl : [
'<div id="contact-row-{Id}"> </div>'
]
}],
var row = 'contact-row-' + record.get('Id'),
grid = Ext.getCmp(gridId),
if(!grid) me.createSubGrid(record,gridId).render(row);
This works fine. But when the grid receives an update event for a record with certain modifiedFields, that record's rowExpander is rerendered using the rowTpl only, and the inner grid is dangling somewhere. I can access the grid using Ext.getCmp, and grid.rendered is true, but it is not shown. So I guess I have to reattach the grid after the row has been rerendered.
I think I can attach to the update event, and find out whether the rowTpl has been rerendered without the child grid using
if(!grid.container.contains(grid.el))
But is there a way to put the grid back into the dom?
I have tried
grid.container.insertFirst(grid.el);
but this does not work. The element is inserted but the grid is not displayed.
Any ideas?
The way you are doing leads to memory leaks (because your component is not destroy when the grid is re-render).
I suggest to check at : Component Template (http://skirtlesden.com/ux/ctemplate) or if you try to render a nested grid, there was several attempt to build something correct and I think a working one is the following : http://blogs.walkingtree.in/2015/06/30/nested-grid-in-sencha-ext-js/
With my trials, I already was on the right track, and the error was somewhere else entirely. The problem was that my update event fn which did the reattach was executed before the update event fn that broke everything, because the fn was fired on the same event and had the same priority, but was attached to the store earlier. Changing the priority was one option, but I just put the creation into the boxready event, which is executed after the view has attached its events to the store:
xtype:'grid',
listeners:{
boxready:function(grid) {
var store = grid.getStore();
...
store.on({
update:function(store, record) {
me.restoreSubgridDom(record);
},
beforeload:function(store) {
var records = store.getRange();
Ext.each(records,me.destroySubgrid);
}
});
}
}
with the two functions:
restoreSubgridDom: function(record) {
var row = 'contact-row-' + record.get('Id'),
gridId = 'ContactRow'+record.get('Id')+'Grid',
grid = Ext.getCmp(gridId);
if(grid && !grid.container.contains(grid.el))
{
grid.container.insertFirst(grid.el);
}
},
destroySubgrid: function(record) {
var gridId = 'ContactRow'+record.get('Id')+'Grid',
grid = Ext.getCmp(gridId);
if(grid) grid.destroy();
}
I want to implement Master / Detail Functionality in kogrid. So that when I select any field of first grid table all the other details will be shown in next detail grid.
Can anybody have any hint how to implement this.
A create a master/detail grid set you need to use a ko.computed to select/filter the detail.
You need 3 observable arrays and 1 computed.
var model = {
parent: ko.observableArray(),
details: ko.observableArray(),
selectedParents: ko.observableArray()
};
model.selectedDetails = ko.computed( function() {
var selectedParent = this.selectedParents()[0];
if ( !selectedParent ) {
return [];
}
return this.details().filter( function(item) {
// define filter comparison here
} );
}, model );
In your markup, define 2 koGrids
<div data-bind="koGrid: {
data: parent,
multiSelect: false,
selectedItems: selectParents }"></div>
<div data-bind="koGrid: { data: selectedDetails } "></div>
koGrid will populate the selectedItems observableArray with Zero or One item. The computed will execute a filter over the children which the second grid is bound to.
I have omitted the columnDef data bind part from breivity.
If you have an AJAX query to run for the details array, then use a subscription against the "parent" observable, change selectDetails to a straight observableArray and set its contents in the AJAX callback
See this jsFiddle for a basic example