Angular - kendo data binding - angularjs

I'm using a kendo grid and have a checkbox column with the following template:
"<input class='gridCheckbox' id='gridCheckbox_#=name#' name='Selected' type='checkbox' ng-model='dataItem.checked'/>"
In addition I'm also using an observableArray as the grid's dataSource.
When clicking the chekcbox the data in the observableArray is changed as expected but no "change" event is triggered.
Here is how I define the observableArray:
var obsArray = new kendo.data.ObservableArray(scope.gridData);
this.gridDataSource = new kendo.data.DataSource({
data: obsArray
});
obsArray.bind("change", function (e) {
console.log(e.action, e.field);
});
"scope.gridData" is the original dataModel. When I click the checkbox the observableArray is changed but not the "scope.gridData". In order to change the "scope.gridData" I want to listen to the "change" event and change the "scope.gridData" manually but as I said the "change" event is not triggered.
Any suggestions to what am I doing wrong and maybe there is a better solution.

Read This
your issue is that kendo uses a copy of your scope object

I manually added an event to my input checkbox (in our class we're using Angular so it was on ng-click="doSomething()" but maybe yours is just click="doSomething" and recorded handling the boolean change manually.
We have the Kendo Observables, too - but I got **lucky because we're also using the Breeze JS stuff where we can do data detection and refresh the grid once the data propagates backwards to the right place to be set to dirty. ( grid.dataSource.read(); )
If you want the full row value, make the click="doSomething(this)" and then capture it as the Sender. Just debug in and you should the dataItem attached to the Sender.

This might help you & this is not the correct figure but i did one example like this similar to your problem
var contentData = [
{ organization: 'Nihilent', os: 'Window' }
];
var nihl = contentData[0];
var viewModel = kendo.observable({
gridSource: new kendo.contentData.DataSource({
contentData: contentData
})
});
kendo.bind($(document.body), viewModel);
contentData.push({ organization: 'Dhuaan', os: 'Android' });
nihl.set('os', 'iOS');

Related

Null selection error on Bryntum Kanban Task click

I am working on integrating the Bryntum Kanban board into an EXTJS application. In the top toolbar of the kanban, I have an ExtJS combobox that changes the view so that users can view their private taskboard as well as the taskboard for their groups. (Users can be in more than one group) When the view is changed, both the statestore that populates the columns of the taskboard and the userstore that populates the userpicker need to reload, as well as the taskstore. The problem is that after the view is changed, clicking on a task throws two errors:
Uncaught TypeError: can't access property "getRange", this.selected is null
ExtJS 2
relayMethod http://dev.southern-air.com/javascript/taskboard/taskboard-all-debug.js:6471
map ExtJS
relayMethod http://dev.southern-air.com/javascript/taskboard/taskboard-all-debug.js:6470
deselectAll http://dev.southern-air.com/javascript/taskboard/taskboard-all-debug.js:6446
deselectAll http://dev.southern-air.com/javascript/taskboard/taskboard-all-debug.js:7431
onDragStarting http://dev.southern-air.com/javascript/taskboard/taskboard-all-debug.js:7532
ExtJS 4
getDragData http://dev.southern-air.com/javascript/taskboard/taskboard-all-debug.js:4896
ExtJS 86
ext-all-debug.js:200495:9
and
Uncaught TypeError: can't access property "getRange", this.selected is null
ExtJS 2
deselectAllInOtherSelectionModels http://dev.southern-air.com/javascript/taskboard/taskboard-all-debug.js:6465
each ExtJS
forEachSelModel http://dev.southern-air.com/javascript/taskboard/taskboard-all-debug.js:6475
deselectAllInOtherSelectionModels http://dev.southern-air.com/javascript/taskboard/taskboard-all-debug.js:6464
deselectAllInOtherViews http://dev.southern-air.com/javascript/taskboard/taskboard-all-debug.js:7385
onTaskClick http://dev.southern-air.com/javascript/taskboard/taskboard-all-debug.js:7381
ExtJS 2
ext-all-debug.js:200495:9
Here is the code for the change listener on the combobox:
change: function (field, newValue) {
var ts = Ext.data.StoreManager.lookup('taskstore');
var ss = Ext.data.StoreManager.lookup('statestore');
var us = Ext.data.StoreManager.lookup('userstore');
var taskboard = field.up('mytaskboard');
console.log(taskboard);
ts.getProxy().setExtraParam('view', newValue);
ss.getProxy().setExtraParam('view', newValue);
us.getProxy().setExtraParam('view', newValue);
taskboard.deselectAll();
ss.reload({
callback: function () {
// taskboard.deselectAll();
taskboard.refresh();
us.reload({
callback: function () {
taskboard.userMenu.picker.refresh();
ts.reload({
callback: function () {
console.log(taskboard);
}
});
}
});
}
});
}
Is there anything that I need to do before I reload the stores to ensure that this error is not thrown? If anyone has also had this problem I'd appreciate your solutions. I have tried deselecting all before reloading, as you can see in the code above, but that doesn't help either.
After troubleshooting, I was able to find a solution that seems to be working. I had to add the following line to the change listener before reloading the stores:
delete field.up('mytaskboard').selModel;
This line deletes all the selection models from the taskboard, which were the things that were causing the problem in the first place. Now the views change and everything works as expected. I am still interested to know if this may cause other issues down the line though.

How to get the value of selected row directly in HTML using ag-grid

i try to get the the value of number row selected, and print it in HTML using Angularjs, but no issue,
i have the count only when i clic in the grid column header.
The value of " selectedRowsCounter " is 0 in html, when i dosn't clic in the grid header
my code is like
var activeButtons = function() {
var countRowsSelected = $scope.gridOptions.api.getSelectedRows().length;
$scope.selectedRowsCounter = countRowsSelected;
console.log($scope.selectedRowsCounter);
$rootScope.count.selectedRows = countRowsSelected;
};
$scope.gridOptions = {
rowData: null,
angularCompileRows: true,
onSelectionChanged: activeButtons,
}
there is a screenshot
i have open the same subject here
https://github.com/ceolter/ag-grid/issues/1023
i have added this line to activeButtons function and it work fine
$scope.gridOptions.api.refreshView();
i dont knew if there is a good solution, but that work for now
The problem seems to be with Angular being unaware of the $scope property change because ag-grid does not tell Angular that it has modified something in the $scope. Although it is difficult to tell if you don't show your view.
You can use onSelectionChanged the way you are using it to know how many rows have been selected, but you need to tell Angular that something has changed in its $scope by applying it.
Something like this:
var activeButtons = function() {
var countRowsSelected = $scope.gridOptions.api.getSelectedRows().length;
$scope.selectedRowsCounter = countRowsSelected;
console.log($scope.selectedRowsCounter);
$rootScope.count.selectedRows = countRowsSelected;
window.setTimeout(function() {
this.$scope.$apply();
});
};
That way you can apply the $scope and the html view will reflect the changes.

angular-ui-tree: dropped location + catch dropped event in directive

I'm using angular-ui-tree for building a tree of items in my app.
I'm using its drag & drop feature and I need to know when & where (on what element) the dropping occurs.
For example, I drag item1, and drop it on a panel. I want the panel to display the item name. (each item has a name property). the panel is just a simple div with text inside.
I saw in the documentations that I can access the "dropped" event in my controller. But I don't understand how to change the panel content according to the dragged & dropped item.
As in documentations $callbacks (type: Object)
$callbacks is a very important property for angular-ui-tree. When some
special events trigger, the functions in $callbacks are called. The
callbacks can be passed through the directive.
you define the events in a treeOptions collection
myAppModule.controller('MyController', function($scope) {
// here you define the events in a treeOptions collection
$scope.treeOptions = {
accept: function(sourceNodeScope, destNodesScope, destIndex) {
return true;
},
dropped: function(e) {
console.log (e.source.nodeScope.$modelValue);
}
};
});
then in your tree div add callbacks="treeOptions" which you defined above in the controller
<div ui-tree callbacks="treeOptions">
<ol ui-tree-nodes ng-model="nodes">
<li ng-repeat="node in nodes" ui-tree-node>{{node.title}}</li>
</ol>
</div>
then you can access the old parent from here
e.source.nodeScope.$parentNodeScope.$modelValue
and you can access the new parent from here
e.dest.nodesScope.$parent.$modelValue
Hey guys i just found it !
$scope.treeOptions = {
dropped: function (event) {
//To catch the event after dragged
//Value of model which is moving
event.source.nodeScope.$modelValue;
//Source Parent from where we are moving model
event.source.nodeScope.$parentNodeScope.$modelValue;
//Destination Parent to where we are moving model
//Edit: Use "nodesScope" instead of "nodeScope" for dest object
event.dest.nodesScope.$nodeScope.$modelValue;
}};
Hope it works for you too:)
You access the "dropped" item like this.
$scope.elOptions = {
dropped: function(e) {
console.log (e.source.nodeScope.$modelValue);
}
};
Addional information which might be useful can be found on this issue of the project : https://github.com/angular-ui-tree/angular-ui-tree/issues/272
For example in my case, I was dragging from one tree to another one, and in this case, the dropped function must be overriden in the SOURCE tree options (and not the DESTINATION one like I initially thought).
The discussion in the related issue helped me a lot to find this out.

Backbone - Access other views of collection

I have a typical structure of a collection holding models.
In the view, each object has an 'edit' button, that should desactivate all 'edit' buttons of other objects.
I wonder what is the best practice of doing that. Thanks!!
You could add a property editable on your models that is default set to true. Then when you click the 'edit' button on one of the views, you could loop through all the models of the other views and set editable to false. On the view you would listen to model changes, and re-render the view. If editable is false you would disable the edit button.
Ok, so I came up with the following approach:
Assume that model has a property status, and when it is modified to active I want to hide the edit button in other entries (or simply disable it).
My collection view listens to a change in a model:
initialize: function(){
this.listenTo(this.collection, "change:status", this.triggerEditable);
},
The listener callback looks like that:
triggerEditable: function(obj){
var triggerValue = null;
// I am interested in a status which became 'active' or stopped being 'active'
if (obj.get("status") == 'active' && obj.previous("status") != 'active') {
triggerValue = "editable:false";
} else if (obj.get("status") != 'active' && obj.previous("status") == 'active') {
triggerValue = "editable:true";
}
// for any other status change - return
if (!triggerValue) return;
// trigger is fired for all other objects in the collection
_.each(obj.collection.without(obj),function(otherObj) {
otherObj.trigger(triggerValue);
});
}
So, when one object becomes active or stop being active, edidable:false or edidable:true are triggered for all other entries. All I need to do is to add to the model view initializer a listener:
this.listenTo(this.model, "editable:false", this.disableEdit);
this.listenTo(this.model, "editable:true", this.enableEdit);
Here I guess I could combine these two lines into one, first by listening to the editable namespace (how??) and then by passing an argument to the function (again, how exactly?).
From here it is straight forward - implement the listener callback:
disableEdit: function() {
var e = this.$el.find('button.edit')
e.attr('disabled','disabled');
}
If somebody has something to add or to make this solution nicer, I will be glad to hear.
Anyway, hope it will be helpful to others!!

How to reference the event context for events defined in a backbone.js view?

I have my view set up with some events and I want to reference, for example, the button element that was clicked because it has a data attribute I need. I want to do it like so:
events: {
'click #testGadget': 'fireEvent',
...
},
fireEvent: function(){
var x = $(this).data('iCanHaz')
}
But the 'this' variable is scoped to the view itself. I know there's a way to accomplish what I'm looking to do but I can't seem to word my question in a way that returns any google hits.
Can simply be done with the event.target property:
fireEvent: function(e){
var x = $(e.target).data('iCanHaz')
}
see Event Object doc

Resources