Can I update a jQuery collection of objects? - loops

I have inited many elements, which need to animate, so I just want to init them once. I said this up front to discourage you from answering to re-define it, because I'd have to re-define all the events for all the elements in mid-animation.
I have a ul with tens of li, but when I detach one of the Li, the next animation STILL happens on the whole collection of elements that existed when inited. Not on the CURRENT collection.
So I need some way to "update" the jquery object (collection of LIs) to remove the ones that don't exist anymore.
Is there anything provided for that?
I don't know if each collection knows what it was made from for even call it an "update"
so for now I will just test if the parent is still the same and the element is not empty.
Thanks.

A code sample might help us a lot.
But what i understood from your question is that you have a jQuery collection of objects say '$listCollection' from which you remove an li element say 'listElement'(DOM object, not jQuery object), then this is what you want
$listCollection.splice($listCollection.indexOf(listElement),1);
Note: The above code will behave buggy if 'listElement' is not in '$listCollection'

Ok, so in short, what I expected, is that it seems there is nothing provided by jQuery.
I had to make the collection variable global, so the functions that depend on that collection later can see the updated version, rather than passing it (the collection variable) to the events functions which won't be aware of future changes.

Related

What is safe method to perform `Object.assign` when using AngularJS?

Basically I would like to perform Object.assign to get copy of my data, without anything that AngularJS attached in the past, it attaches now, or may attach in future versions.
Sure I can delete such property as $$hashKey after assignment but this approach is totally fragile, on the other hand I could manually construct the object with fields I want but this on the other hand is tiresome (and also fragile if I change definition of my source object).
Is there something solid in between?
There are no other properties as $$hashKey, it is one of a kind.
All of Angular object helpers are aware of this property and remove it at the end of the operation. angular.extend is a direct Angular counterpart of Object.assign and should be used instead.
angular.copy seems to be helpful in this case

Detaching dynamics $scope

Good day to all.
There is a problem.
Create one object $rootScope.metaContent (need just $rootScope). In the future, to work with the data of the object, creating a new based on the first $scope.addMeta = $rootScope.metaContent. Needless to say, when I'm working with the second (adding an object, change its data or purify) is changed first. But I need to work with the second ($scope.addMeta), that would be the first not changed. It is necessary to restore the data to the source by pressing one button "Undoing".
How can they decouple from each other???
Thanks in advance!!!
You can create a deep copy of an object or an array in angular using angular.copy
$scope.addMeta = angular.copy($rootScope.metaContent);

How does angularjs react for changes of objects in the scope?

If there is a view that displays elements in an array, and the array grows; how does angular refresh the DOM? Does it just append the new elements to the existing view or recreates the whole thing?
I fear that I might run into a Schlemiel the Painter's algorithm if I keep adding stuff to lists...
The api appends a new element to the end of the dom tree (well at least the section you are working with) or beginning depending on the filter mechanic you implement. You should be safe, adding as many elements you like of course there is a limit to how big you can get in reality. However for sane amounts of items you should be perfectly fine.

Angularjs: Find all instances of a directive

I'm trying to create a directive to allow the user to navigate the page with arrow keys by section. But I also want to be able to have those sections be scattered around the dom, and to have this not break when stuff gets added and removed. I can think of several ways to do this, but none of them are satisfactory:
Create a directive with a controller that lets other directives register themselves (and unregister on $destroy). But this will be out of order if I add something in the middle later. Also, I've tried writing it this way, and it seems like way more code than necessary.
Whenever the user hits an arrow key, make an empty array, and $broadcast an event, with a callback for directives to register themselves on that list. Then, once that list is full, advance or go backwards on it. They (should?) come back in the order they're in on the DOM, but I'm not sure since this way seems crazy and hackish.
Mark things that are 'tabbable' with css, and write this the simple way in jquery, something like this: On a new click event, var all = $('.tabbable'), and then do the obvious with that. But I really don't want to do it that way, because it's not 'the angular' way. Not out of some sense of purity, but because I'm building this as part of a larger library of widgets, and I want this functionality to be accessibly to them.
So, is there any way for me to get the scopes of all directives of a certain type, without resorting to weird hacks, or spreading the logic out all over the place?
This is a good question. +1
First, finding all directives or nodes by type goes against the Angular way. The View is the official record in AngularJS, so directives should say what they do and do what they say. Coding some process somewhere to scan for DOM nodes and act accordingly is problematic for several reasons, not the least of which are separation of concerns and testability.
I'm glad to see you're looking at other options, but I agree that the other options you provided are sub-optimal for the very reasons you mentioned. But I have one more. This is one that I've used for a different application, but that required knowledge of scattered DOM nodes.
First, we create a service to manage the state of this component. It's simple. Let's call it SectionsService. Next, we create a directive to register sections. Let's call that section for simplicity. The section directive registers the DOM node's ID (maybe created programmatically to ensure uniqueness) with the SectionsService during its linking phase. Since the DOM is processed (mostly) in order, the nodes added to the SectionsService will also be in order. So the DOM looks something like this (irrelevant stuff omitted):
<div section>...</div>
<!-- other stuff -->
<div section>...</div>
<!-- other stuff -->
<!-- etc. -->
(Though out of scope here, it would not be very difficult to program it in such a way that the order wouldn't matter, but it'd be based on specifics of your app that I don't know.)
Next, you create your triggers, like an arrow key handler. On these events, you simply tell the SectionService to go to the previous/next node in the list. AngularJS comes with a service called $anchorScroll that can be used to emulate the browser's hash-based positioning we're familiar with. You could obviously also use a jQuery plugin to animate the scrolling if you wanted to.
And that's it! A very simply directive, a fairly simple service, and whatever trigger(s) you need. All told, I'd guess less than 100 lines of code including tests. All components are decoupled and easily testable, but still really quite simple. The view remains The Truth. The Angular Way is preserved.
And there was much rejoicing.
I hope this sets you on the right direction, but of course feel free to ask a follow-up question. We can also talk code specifics too if you'd like; as I said, they wouldn't be very complicated.
AngularJS services are singletons and can be required via dependency injection. You could have your directives require a state manager service and call incrementers/decrementers.
Alternatively, a little easier but more brittle, you could keep an array in $rootScope. It's more idiomatic "angular" (but not by much) than a jquery selector global, but probably not the best route if you're building a widget library.

Backbone View.remove()

I just upgraded my Backbone to 0.9.2 and when I do a view.remove() like I did with the older version it no longer is working for me.
I have a popup.js view called processingView that just has some jquery code wrapped in an view extend. I assign this to a variable called processing.
this.processing = new processingView();
When I fire an event to remove the processing object from the Dom by saying. this.processing.remove() it no longer gets removed. If I revert back to the older version of Backbone it works.
Anyone got any ideas why this would be.
My code is a huge amount of source files so its hard to paste all this in here. But as far as what I'm trying to do it should be straight forward remove a view object from the dom.
ANSWERED MY OWN QUESTION
Ok I was not using setElement when I was manually setting View.el
If you've ever manually set this.el in a Backbone View to be a particular DOM element, you'll want to use setElement instead.
Its still not clear what the difference between view.el and view.$el. Maybe someone can straighten that out for me.
view.$el is equivalent to $( view.el ). It's a convenience so that you don't have to incur the hassle and additional overhead of repeatedly calling the jQuery constructor. You may want to structure your code (if possible) so that you don't need to manually set el and call setElement. You can see my answer to another question for an example.

Resources