One of the things I'm still hung up on with Angular is understanding all of the lifecycle hooks and when to use what when.
I often need to stick a little plain'ol JS into a component to deal with some DOM issue that, alas, I can't handle via Angular (usually because I'm working within a component that needs to access some elements from a parent component's rendered DOM that we have no access to the Angular code for...I do realize this isn't the 'proper' Angular way but...).
An example right now is a few pages I'm working on that use a component need that needs to hide a DOM element on the page that isn't a part of this component. I need to use JS for this (a whole other story why CSS isn't the solution for this one).
But I only want to do this once the DOM is fully rendered.
Sometimes this seems to work when inserted into ngAfterViewInit -- but sometimes not. It seems that there's no guarantee the full DOM is ready using that lifecycle.
Moving that logic into ngAfterViewChecked does work. However, the issue with ngAfterViewChecked is that it's getting called dozens of times on some pages--and the first few times it's called, the DOM isn't even ready. Not the end of the world, but there's no reason for me to be attempting to grab the same DOM object 40 times per page render. I somewhat remedy this by adding a boolean flag to tell this bit of JS to stop running once it finds the DOM elements but that's hacky.
So my question is: What is the proper (if there is one) way to handle JS manipulation of the DOM after the DOM is fully rendered in the context of an Angular component? Is it to use one of the angular lifecycle events? Something else? Or this whole idea of manipulating DOM objets outside of the component I'm working in just anathema to the 'Angular way' so just isn't something accommodated within Angular?
How to get component handler in Ext Js?
what are the different ways to get them like
this.lookupReference('ref-name-of-class')
this.lookupReferenceholder('class-name')
this.findParentByType('name-of-xtype')
Ext.ComponentQuery.query('alias-or-id')
Ext.getCmp()
this.up()......
this.down().....
Can anyone list all of them?
Gloabal IDs and Ext.getCmp() is a bad practise. It's slow and colliding global IDs will break everything.
container.getComponent() is also a bad idea. If nesting changes, everything will break.
parentComponent.query() should be used when you want to get multiple child components which are relatively close to the parent. If you want to get a single component, you should use down() method instead. There won't be a big performance hit if the child component you are searching is pretty close to the starting node.
lookupReference() or just lookup() is recommended right now but it will only work within single view or viewController class.
I'm fairly new to Vue.js and I ended up manipulating an array on a parent component using $parent. I'm just wondering if there is some danger in doing it like this:
setTitle(title) {
this.$parent.items[this.index].name = title;
this.editTitle = false;
}
Instead of emitting an event with $emit, and then listening for that on the parent?
Will this burn me in any way in the future?
I' wondering because I've never seen it showed like the first solution in any of the tutorials I've come across.
There is some danger in manipulating a parent through a child, similar to manipulating a child through a parent. The main issue tends to come in separation of responsibility and coupling, if you reuse the code you need to remove or modify any code that manipulates another object in the system.
By emitting an event and letting the parent handle the updated information you can reuse the object in multiple places without modification as any parent that doesn't need to update their items can just ignore the event.
It also makes it harder to maintain the code as someone might see the array get updated but not see the code in the parent object that updates it. In your example it would not be hard to find but if your program became more complex it could take time to find and update or debug.
I am newbie to jQuery. I am bit confused whether is it fine or may cause memory leak ?
Here is the code: This method is called on certain date filters for each new values
function preapreTooltip(chart) {
var tickLength = chart.xAxis[0].tickPositions.length,
ticks = chart.xAxis[0].ticks,
tickPositions = chart.xAxis[0].tickPositions;
for ( var iCntr = 0; iCntr < tickLength; iCntr++) {
var tickVal = tickPositions[iCntr];
//.label or .mark or both
(function(tickVal) { // Is this good practice to call function like this?
ticks[tickVal].label
.on('mouseover', function(event) { // Is this good practice to call function like this?
var label = '', labelCnt=0;
$(chart.series).each(function(nCntr, series) {
//business logic for each series
});
// calling method to show values in a popup
});
ticks[tickVal].label.on('mouseout', function(event) { // Is this good practice to call function like this?
try {
hideWrapper(); // hides popup
} catch (e) {
// do nothing
}
});
})(tickVal);
}
}
Whilst there are browser specific issues that need to be avoided when writing large pure JavaScript projects, when using a library such as jQuery it should be assumed that the library's design helps you avoid these problems. However, considering memory leaks are rather hard to track down, and each different version of a particular browser could behave differently - it is far better to know how to generally avoid memory leaks than being specific:
If your code is being iterated many times, make sure the variables you are using can be discarded by garbage collection, and are not tied up in closure references.
If your code is dealing with large data structures, make sure you have a way of removing or nullifying the data.
If your code constructs many objects, functions and event listeners - it is always best to include some deconstructive code too.
Try to avoid attaching javascript objects or functions to elements directly as an attribute - i.e. element.onclick = function(){}.
If in doubt, always tidy up when your code is finished.
You seem to believe that it is the way of calling a function that will have an effect on leaking, however it is always much more likely to be the content of those functions that could cause a problem.
With your code above, my only suggestions would be:
Whenever using event listeners try and find a way to reuse functions rather than creating one per element. This can be achieved by using event delegation (trapping the event on an ancestor/parent and delegating the reaction to the event.target), or coding a singular general function to deal with your elements in a relative way, most often relative to this or $(this).
When needing to create many event handlers, it is usually best to store those event listeners as named functions so you can remove them again when you are finished. This would mean avoiding using anonymous functions as you are doing. However, if you know that it is only your code dealing with the DOM, you can fallback to using $(elements).unbind('click') to remove all click handlers (anonymous or not) applied using jQuery to the selected elements. If you do use this latter method however, it is definitely better to use jQuery's event namespacing ability - so that you know you are only removing your events. i.e. $(elements).unbind('click.my_app');. This obviously means you do have to bind the events using $(elements).bind('click.my_app', function(){...});
being more specific:
auto calling an anonymous function
(function(){
/*
running an anonymous function this way will never cause a memory
leak because memory leaks (at least the ones we have control over)
require a variable reference getting caught in memory with the
JavaScript runtime still believing that the variable is in use,
when it isn't - meaning that it never gets garbage collected.
This construction has nothing to reference it, and so will be
forgotten the second it has been evaluated.
*/
})();
adding an anonymous event listener with jQuery:
var really_large_variable = {/*Imagine lots of data here*/};
$(element).click(function(){
/*
Whilst I will admit not having investigated to see how jQuery
handles its event listeners onunload, I doubt if it is auto-
matically unbinding them. This is because for most code they
wont cause a problem, especially if only a few are in use. For
larger projects though it is a good idea to create some beforeunload
or unload handlers that delete data and unbind any event handling.
The reason for this is not to protect against the reference of the
function itself, but to make sure the references the function keeps
alive are removed. This is all down to how JS scope works, if you
have never read up on JavaScript scope... I suggest you do so.
As an example however, this anonymous function has access to the
`really_large_variable` above - and will prevent any garbage collection
system from deleting the data contained in `really_large_variable`
even if this function or any other code never makes use of it.
When the page unloads you would hope that the browser would be able
to know to clear the memory involved, but you can't be 100% certain
it will *(especially the likes of IE6/7)* - so it is always best
to either make sure you set the contents of `really_large_variable` to null
or make sure you remove your references to your closures/event listeners.
*/
});
tearDowns and deconstruction
I've focused - with regard to my explanations - on when the page is no longer required and the user is navigating away. However the above becomes even more relevant in today's world of ajaxed content and highly dynamic interfaces; GUIs that are constantly creating and trashing elements.
If you are creating a dynamic javascript app, I cannot stress how important it is to have constructors with .tearDown or .deconstruct methods that are executed when the code is no longer required. These should step through large custom object constructs and nullify their content, as well as removing event listeners and elements that have been dynamically created and are no longer of use. You should also use jQuery's empty method before replacing an element's content - this can be better explained in their words:
http://api.jquery.com/empty/
To avoid memory leaks, jQuery removes other constructs such as data and event handlers from the child elements before removing the elements themselves.
If you want to remove elements without destroying their data or event handlers (so they can be re-added later), use .detach() instead.
Not only does coding with tearDown methods force you to do so more tidily (i.e. making sure you to keep related code, events and elements namespaced together), it generally means you build code in a more modular fashion; which is obviously far better for future-proofing your app, for read-ability, and for anyone else who may take over your project at a later date.
Here is an excellent article to detect memory leak using Chrome or Safari : http://javascript.crockford.com/memory/leak.html
It is use not well known functionalities of Developer Tools panel.
Interesting and very useful!
EDIT
It was not the good link (but still useful). Here is the one : http://gent.ilcore.com/2011/08/finding-memory-leaks.html
If I bind an event to a DOM element, does the event ever get destroyed if the element does? By destroying of an element I'm referring to removeChild(). A move of the node to another location with appendChild() leaves the event listener untouched.
Basically I'm interested in this because I want to know if I need to do some cleanup/tear down.
I think you mean event handler here, right? If so then it is a valid concern for garbage collection purposes to be careful with functions attached to elements via "onfoo" attributes. IE has what amounts to separate garbage collectors for the DOM and for JavaScript, and they don't know much about each other.
I believe what suffices is to make sure that "onfoo" attributes are set to null when DOM elements are tossed aside. By so doing, the JavaScript code will have broken the reference to JavaScript memory allocated for the handlers, so the DOM garbage collector won't leak. Of course this goes for any other random attributes you may have added to DOM elements too.
Though I hate to suggest using a JavaScript framework for questions not so tagged, and in fact I won't actually make such a suggestion here, but I will say that one of the things frameworks (usually) do for you is try to keep the DOM "clean" in this kind of situation.