I need to create sortable drag and drop lists in my application. So, for this I have used angular-drag-and-drop-lists which works fine for an small amount of items.
However, my application migh have thousands of items. So, to improve speed, I need to use md-virtual-repeat offered by Angular Material. It keeps the model in the background with the right number of elements. But, the DOM only renders those that are visible within a virtual container.
Because the library uses the rendered $index to keep track of the elements, using the virtual repeater creates all sort of problems since the $index now is virtual.
Some of these problems for instance are:
Dragged element gets duplicated in the model
Element that was in drop location gets deleted from the model
During dragging some elements might get lost from the original model
Etc...
What do you suggest to attack this problem?
Are there any other easier solutions rather than using this library?
Thank you
Related
We have a large number of angularJS 1.5 directives (around 100) that we use throughout our applications. We also use slickgrid almost everywhere to display mass amounts of data. A project has recently come up where it would be ideal to be able to use our directives within slickgrid cells. So I've been trying to write a slickgrid editor to generate our directives when you go to edit one of the cells.
It seems as though angularJS doesn't pick up on the directive (because slickgrid doesnt operate within angular) and doesnt attach the element to its lifecycles. so basically the base element and its settings will appear in the HTML like this:
<div class="slick-cell l2 r2 active selected" title="">
<custom-directive></custom-directive>
</div>
but since angularJS doesn't process the directives there's no visible element in the view and none of the transcluded elements are created.
I've tried using $compile to sort of pre render the elements and then send them to slick grid, but that results in multilink errors which I'm not sure how to resolve.
I've also tried using a JS template with the hope that the template could be rendered and then used in a slickgrid editor later, but I haven't had success with that as of yet. I am still trying to make this approach work since I've seen other examples of using templates with slickgrid, but they aren't using angularJS so my situation doesn't quite fit to theirs.
To summarize I'm looking for suggestions on how I might approach this problem. I know slickgrid isn't technically supposed to be used in this fashion but there has to be a way to make this work. Reusing 100+ pieces of code to extend functionality here would be a very huge win.
i got a little bit confusion about ng-repeat and collection-repeat
ng-repeat
<ion-item ng-repeat="item in items" >
...
</ion-item>
collection-repeat
<ion-item collection-repeat="item in items">
...
</ion-item>
the above both lines are doing well and same.
Please let me know if any difference there. also i have 1000 items, so which one is better for this scenario? and how's the rendering speed and what about the performance status ?
collection-repeat is not part of angularjs. As far as I can see it's coming from Ionic Framework. As documentation says collection-repeat was created to be used instead of ng-repeat as it might work better with large number of items.
collection-repeat allows an app to show huge lists of items much
more performantly than ng-repeat
Collection repeat is Ionic's buttery-smooth solution for scrolling huge lists. collection-repeat can be used for large list of items and it has high performance when process huge data set.It renders into the DOM only as many items as are currently visible.This means that on a phone screen that can fit eight items, only the eight items matching the current scroll position will be rendered.
ngRepeat part of the angular Core module. The ngRepeat directive instantiates a template once per item from a collection. Each template instance gets its own scope, where the given loop variable is set to the current collection item, and $index is set to the item index or key.
Based on the use case you can use any of the options. However, if you use ionic framework for mobile then I would suggest to go for Collection repeat.
Further, If you need to use ng-repeat, it is recommend to process data in the server side and request part by part. This way you can expect high performance and less processing in the client side. Another option is store the large data set in the client browser and then process data using that data set.
In case of 1000 elements I would strongly recommend the collection-repeat. It's more flexible, and it renders as many items from collection as many can fit the screen. the rest is loaded dynamically, you can even use 200k collection and it will go smooth as well. ng-repeat renders the collection items until it's done, so it will give you much worse performance.
So collection-repeat it is my friend.
Good luck with your development!
Note: collection-repeat is not a part of angular core, look here for more : http://ionicframework.com/docs/api/directive/collectionRepeat/
From what I'm understand is ng-repeat is suitable to use for small numbers of item and collection-repeat is very suitable to use for huge numbers of item. Its actually about the performance when it comes to view/render in a device. For more understanding you can see this video, it really help me to understand both of it.
In Simple Word -
Ionic has a collection-repeat directive that you can use, instead of ng-repeat, when you need to display very large lists.
How it works?(Deep)
The module is divided into two components, $repeatFactory (a service where helper functions are defined) and collectRepeat (a directive where most of the logic lives).
The most important takeaway from the factory is the repeatManager method. It is the contructor that is instantiated at the beginning of the link function of the directive and is responsible for maintaining the state of the scrolling view.
On creating a new instance of repeatManager, it's also necessary to generate a new object (or map) to provide as reference for all the items that have already been transcluded, rendered, and whose scope has been updated. The enclosing parent element must also be registered so that we can later change it's height to the height of all the items in the collection.
Next, a watch is set on the collection with an anonymous function set to be invoked whenever the collection changes. This is where the bulk of the logic resides. It's split into three steps.
Transclude and render the first element of the collection so that the height and other properties of each individual item may be registered, the height of the parent div adjusted, and the size of the viewport calculated
With the size of the viewport determined, loop over and render the n number of items that will fit inside the viewport (plus a few extra for smoothness).
Set a 'scroll' event listener on .scroll-content to return the scrollHeight of the first element of the collection and render only the necessary elements.
There are a few additional tidbits (also known as comments) available in the code below. It should help alleviate some confusion if you have trouble following the above synopsis. The module is also available on github.
GitHub
Differences - Working Example
Code Here
I have a list with quite a few elements (each of them is a nested div). Each element has a custom onclick handler.
JS updates the list several times per second, this may result in:
adding or removing some elements
changing text in some elements
changing styles in some elements
changing height of some elements
etc.
Most of the time the update makes small changes to the majority of the elements.
To minimize reflows I should remove the list from DOM, make the changes and append it back. The problem I have with this approach is that when user selects some text, the next update will reset the selection. (And the next update comes within a second) If user clicks a button his click may fail to register if there was an update between mose_down and mouse_up.
I understand when the selection resets on text that have been changed. It makes sense. But with such approach any selection in this list will reset.
Is there any better way to do this? How would you implement such list?
This list is fully generated by JS. If I'm removing it from DOM anyway, is there any benefit to modifying it instead of recreating it from scratch? Creating it anew each time would require less code.
This sounds like 2 way data binding, there are a couple of good custom solutions to data-binding answers on here: Handy stack link. Alternatively backbone.js and knockout.js have good techniques amongst quite a few other frameworks (angular ect).
Additionally, if you want to have a pop at it yourself (which I highly recommend to get a better understanding) you could use the proposed 'Object Observe' function. There's some handy documentation with some examples on how this works over at Mozilla. as well as The trusty HTML5 Rocks, which is a nice simple tutorial on using the new Object.Observe functionality, well worth a read.
Hope this helps!
Recently I had to make an interface that necessitated many items with numerous checkbox fields to be displayed and interacted with (here is a link to a screengrab of a small portion of such a list http://i.imgur.com/hMtGSL4.png).
My issue was that AngularJS would get unreasonably slow pretty quickly. My question is What steps could one take to optimize ng-repeat and displaying items with many fields?
I have tried with varying degrees of improvement (based on what I could come up with and other stackoverflow posts):
Formatting the data before it gets to the view so as to not use any AngularJS filtering/sorting.
Simplifying the data as much as possible (checkbox fields being arrays of booleans, etc)
Splitting the data into groups that, when clicked, loaded the relevant items (hence the gray bars in the picture). This is more of a pragmatic solution though, rather than straight up AngularJS optimization.
Lazy loading scroll, scrolling to the bottom of the screen loads more items below the fold (also, more of a pragmatic solution).
Using directives to dynamically generate a form, and then use jquery for saving the data after manipulation. Without $watch on items anymore it certainly was more efficient, but largely defeated the benefits of using AngularJS.
Thank you, and hopefully this question and its answers can serve as a good resource for AngularJS specific techniques one can use in such a situation.
I'm using jQueryUI to create a large table of sortable cards, each of which is composed of a large tree of nested div tags with styling using CSS. When I drag a card under certain conditions, I want to create a slightly transparent "clone" of the card that hovers just to the right of the "real" card while dragging, but I don't want to actually duplicate all of the HTML in order to accomplish this visual effect.
So, is it possible to use javascript to draw the same DOM element on a webpage in two different places without actually duplicating the HTML?
Thanks to anyone who answers.
Each DOM element is either not connected to DOM at all or connected to one specific parent. You cannot display same element in two different places. Attaching to a new parent will just move element from old one.
You can either use cloneNode (take care to attach new event handlers to it, as they are not cloned) or make at JS factory that produces some "template" elements and attach each of them to different parents.