I am relatively newer with Angular so please excuse my mistakes, if any. I have to modify and use this treeview directive from NgModules. It's code looks promising but I have to modify it a little bit to add the functionality of add/ delete or modify items.
Plunker
I was previously using jQuery to create my treeview and have accomplished all the relevant tasks. But since I decided to shift to Angular, I have to do it the angular way.
So as far as I could understand this directive uses nested recursive directive to create the tree, which is an efficient way to do it. It works fine, but I would have some 3000-4000 items to show in my treeview. So when I do that with this code it slows down the screen and consumes much memory due to the many watch expressions (5-7 per item).
Plunker
I have tried one time binding in ng-repeat with :: notation. That has helped a lot but now I couldn't implement my add or update methods. Is there any way I could accomplish this?
<li data-ng-repeat="node in ::' + treeModel + '">
https://plnkr.co/edit/KwnvyslibWd1dmIXxBYU?p=preview
You already had the selected node in the scope, so simply push the new node into it's children array.
$scope.AddNode = function(NewNode)
{
NewNode = {"roleName" : NewNode , "roleId" : "role11", "children" : []};
$scope.mytree.currentNode.children.push(NewNode);
};
edit: As name suggest - it is one time binding, so adding/removing won't work here. I think it's only normal that browser get's a bit stuck when trying to display such amount of data once. Instead, you could add nodes by bits, say 20 a step. Or you could check out other libraries as well. This one gives you the option to display array of nodes collapsed at first.
Related
I have started a demo app and come across this problem where my parts that I am adding to the repairs are not being properly proccessed. This is my first angular that I am building.
To get the bug press update on one of the repair cards and then scroll down to the quantity and repair item section at the bottom of the form and try to add a new item. it doesnt regester what is in the form.
This is the codepen with the full view that doesnt work.
This is the function in the controller to pass the info the factory.
$scope.addPartsPerRepair = function() {
partFactory.addPartsPerRepair($scope.newPartsPerRepair);
$scope.newPartsPerRepair = {};
};
This is the function in the factory to add the new repair to the array partsPerRepair
factory.addPartsPerRepair = function(newPartsPerRepair) {
partsPerRepairs.push(newPartsPerRepair);
};
After I abstracted away the repair factory and simplified my view we are left with this
This is the codepen with the partial view that does work.
I have been over this code for the past 6 hours trying to fix this one probelm and I can not see my issue.
Secondly, This is more of an add-on question, Does anyone have any advice on how to save the partsPerRepair to the actual repair[Idx] instead of in one array called partsPerRepair that every repair accesses. I thought I might be able to add an array called parts to each repair and store quanity and item name in that array but that has proven to be more difficult then I can manage. I realize I am asking two different questions but since your here reading I figured you might be willing.
Thanks in advance for any help.
An updated CodePen.
So I've tried to resolve both your questions here, but all I have edited is the arra yof repairs and the add parts method, which means there is alot of cleaning up chanegs to be made like deleting the old partsPerRepairs and its references.
First thing newPartsPerRepair needed to be intialized this is why add parts was not working the function was passsing undefined(anything used as model in ng-model needs to be intialized), which is done in the controller - $scope.newPartsPerRepair = {};.
Second I moved the partsPerRepairs array into the repairs array and called it parts this is under each customer in the array, this is to answer your second question.
Third I changed the way the ng-repeats work to use these new parts arrays - ng-repeat="partsPerRepair in repairs[$index].parts track by $index"
Finally I moved and edited the addNewParts to the repairs factory so it used the new parts array and could access the repairs array.
Hope this all helps.
I'm encountering performance issues, I think due to lots of watchers in the page (more than 4000!!). The scenario is a (small, about 5) list of items in ng-repeat once, each one contains another ng-repeat for every day of week (so 7), and in each day container there are 1 or 2 input field. Each day's element has its own scope and controller and some watch at parent's properties, in order to update parent state at child changes. So a bit complex scenario...imagine an agenda view where each day as some input fields or buttons which update same property in the main scope, like "10 days selected/filled/clicked".
I started with about 5000 watchers, now reduced to about 4000 removing some filters and switching to translate-once directive insted of translate (angular-translate).
So the main question is:
How to further reduce the number of watchers?
Is every child scope inheriting the parent watchers, resulting in 7x for each watcher? If I remove child's controllers, leaving the job to the the parent (passing in the function the child item), will I decrease the number of watchers? Could this be a solution? Any help is appreciate.
In our experience that number of watchers cause no speed problems. The performance problems we have encountered in the last 8 months of development on a single big application were caused by slow third part's components.
For example, we have a page with two drag and drop trees with 14.600 watchers (because of high number of items in both trees). We experienced performance problems because of the component used, angular-ui-tree, and we reduced them opening the page with most of the tree collapsed.
We cannot change that component because it is the only one which features drag and drop between trees, but in another page where we had drag & drop between simple lists we have tried those two components: angular-dragdrop and angular-drag-and-drop-lists. The first had a lot of performance problems (with about 500 items) while the second run really really fast. In his documentation on github, section "Why another drag & drop library?" you can read why it is so fast and why the other is so slow.
So, I can speculate that third part's components bring you the real performance problems, and not the watchers.
In any case, we often write our watchers with a check like the one below to not run the code unless needed.
$scope.$watch('variableToWatch', function(newValue, oldValue) {
if (newValue === oldValue) {
return;
}
... watcher code ...
}
Another way to reduce watchers from html is using one-time-binding.
Example:
<div ng-if="::vm.user.loggedIn"></div>
Related to performance... - One pattern i came up with is to use a private object and assign the prototype of a function for easy access. then in any function ,controllers, directives...ect you can access the prototype of other function,controllers,directives easily. instead of using watchers you can use this pattern like a event loop. instead of angular running 300+ watchers every digest cycles. using this pattern only what triggers the function call matters.
An example of this pattern
var private = {} //accesable to entire app
var app = angular.module('some-app',[])
.controller('someCtrl',['$scope',someCtrl])
.directive('someDirective',someDirective);
function someCtrl($scope){
private.someCtrl = someCtrl.prototype
someCtrl.prototype.update = function(someDate){
//do something....
//access to someCtrl arguments
$scope.something = someDate
}
}
function someDirective(){
var someCtrlProto = private.someCtrl;
return{
link:function(scope ,elm ,attr){
elm[0].addEventListener('click',fucntion(){
someCtrlProto.update(someData)
});
//or
elm[0].addEventListener('click',someCtrlProto.update) //to trigger someCtrl.update from here
}
}
}
After searching and reading docs, I can't find a straight-forward solution to this problem:
Rendering a list of items from an ArrayController, I want to insert a position or page indicator every N elements.
I would appreciate any ideas on the Ember way to do this!
Normally I would assume, that this could be handled in the template, something like...
each listitems
if index % 5 == 0
insert indicator
... but Ember doesn't expose the index and Handlebars templates are supposed to be logic free.
Second approach I can think of is to use the ArrayController and set a property on every nth object in the array, but why should the object need to be aware of this? Setting a property feels like cluttering and a lot of potential for errors.
Any ideas would be highly appreciated!
You can build your own helper. BTW you can access index using _view.contentIndex inside each. So you can write a custom helper which basically inserts required html.
Ember.Handlebars.registerBoundHelper('indicator', function(index,options){
var html = '';
if(index%2) {
html = '<hr />';
}
return new Ember.Handlebars.SafeString(html);
});
And call that by passing index. Here is the working jsbin
http://emberjs.jsbin.com/niguwa/1/edit
Could any one please give a full example of how dispose and destruct are working in qooxdoo 1.6 ? , I can't find any good example in the qooxdoo demos or documentation.
thanks in advise .
Disposal and destruction are in reality the two sides of the same coin: Disposal is the act of destructing objects. Their difference might become clearer to you by thinking of __destruct() as an onDispose() method.
As a rule of thumb, any class that creates QX objects is responsible for their proper destruction. Normally this is done the class' destructor, but may happen at any time depending on your business logic.
Disposal is done via the (ex.)
this._disposeObjects("_buttonOk", "_buttonCancel");
this._disposeArray("_children");
this._disposeMap("_registry");
calls. Some classes may provide explocit methods for their destruction, as in qx.ui.core.Widget
You don't need to implement dispose if you work with object. Only destruct is needed, and not for everything (see above to catch which one you should delete, which one you don't need to)
It will looks like this :
qx.Class.define("q.view.Home"),{
extend : qx.ui.core.Widget,
construct:function(){
this.base(arguments);
},
members:{
__qooxdoo_object:null
},
destruct:function(){
this._disposeObjects("__qooxdoo_object");
}
});
As simple as this.
On the memory management link : this is extremely important : "qx.disposerDebugLevel" : "2"
It will automatically report (on firebug for example) object who are not properly destroyed.
So you will be able to know exactly what you should delete, what is deleted in a proper way.
Also, imagine this, you got a container (Composite for example, or anything) with 5 children and you want to empty the content but not the container, you should do like that :
(according container is the parent element of all children)
var childrenList = container.removeAll();
for(var i=0; i<childrenList.length; ++i){
childrenList[i].dispose();
}
If you only dispose objet for some reason i don't know the Widget class (in qooxdoo framework) sometimes raise error. If you only removeAll, it will not dispose children but only remove them.
If you do both (dispose and removeAll), you will have no problem and children properly disposed.
Maybe the document in the qooxdoo manual about memory management could be helpful:
http://manual.qooxdoo.org/devel/pages/development/memory_management.html
I will first explain what I'm trying to do then I will explain why just in case you get bored of reading the whole scenario.
Basically I have some HTML markup stored in a variable I now need to a wait to access the different elements within the variable. For example:
var markUp = "<h3>h3 tag</h3><p>paragraph tag</p>";
What I need to know is if there is a way for me to query the variable to retrieve say the h3 tag, in a similar way you would use the query function ? I have seen some other practices where people append the var to a hidden div then query the div. I would prefer to avoid this but if that is the only way I will proceed.
I have come across this problem whilst developing a drag and drop application, on drop i use a custom creator function to change the items structure once it is dropped.
If further explanation is needed please say, thanks advance Jonathan
You can use dojo._toDom to create a DOM fragment from your string.
var markup = "<h3>h3 tag</h3><p>paragraph tag</p><p>another paragraph</p>";
var domFragment = dojo._toDom(markup);
dojo.query("p", domFragment).forEach(function(element,i) {
console.debug(element.innerHTML);
});
The underscore prefix in _toDom means that it's a "private" member method of dojo. Normally, it's bad practice to use these as if they were public (like I do here). However, in the case of _toDom I believe it's generally considered acceptable, and according to this trac entry, it sounds like it'll be made public in the next version.