Angular translate attribute vs filter - angularjs

Which of these two is better?
<span translate="key">Key</span>
or
<span>{{'key' | translate}}</span>
They are both good and work fine but in first case I must fill the content of the element.

Using the attribute is better performance-wise, especially if you intend to use translations on elements that will be inside ngRepeats. This is because the way filter work internally.
Every time there is a digest cycle, angularjs reloads all the expressions containing filters. This is because angular can't possibly know if a filter has changed or not. What this means is that, even if the key of the translation has not changed, but some other value on the scope has, angular will look through every translation and translate it again, just to come to the conclusion that they all remain the same.
Attributes are smarter, because the developer of the directive has explicit control over when it should re-render and what watcher should be created.
Edit: And as far as I know, there is no need to fill the content in the first use-case. You can just leave it empty.

Related

Delay generating directive until after page is ready and responsive

I'm working on a single-page app where some parts are really slow. They're slow because I'm displaying 400 complex things in a repeater for the user to scroll through. Each thing is generated by a fairly complex directive that does a ton of data binding and expression evaluation, adds one or two click handlers, and displays a couple of images. In some cases, I also need a grayscale CSS filter on those images, but that really seems way too slow.
I have of course already turned most of my data binding into one-time data binding, but simply generating the 400 things for the first time is still slow. It's initially hidden through ng-if, which speeds it up when I'm not showing it, but once I do need to show it, everything waits 10 seconds for that to happen. I would like to load it in advance, but using ng-show instead of ng-if means the loading of the entire app has to wait for this.
What I would like, is to load the rest of the app, and then, while we wait for user input, start creating these 400 things so they're ready once I need to show them. I don't want the user to notice how slow this is.
Problem is, I have no idea how to do this. Any ideas?
Edit: Having thought about this (and discussed this with my wife), I'm seeing two options (that I conceptually understand, at least):
The easy, quick, boring and cowardly solution is to simply not show the 400 things at the same time, but cut them in pieces and show 40 at a time. That should make it a lot quicker, but also less nice, as the user needs to click around to access all the data.
The interesting solution is to write a new ng-repeat that generates the 400 transcluded copies of the template each in their own asynchronous event, so they don't block user interaction. I really like this idea, but there's one big downside: it's an ambitious idea with deep Angular magic, and I don't have much time available.
OK, not seeing your code structure, through Q&A, I'm trying to get clarification. If I understand you correctly, I believe the solution is to process your images asynchronously and remove reliance of creating/processing them on the fly when the view is visible (i.e. via clicking on a button/tab to 'show' the array 'view' and thus triggering the ng-repeat). BTW, this solution assumes the delays are because the images are being processed rather than because they are being shown.
METHOD 1 (less preferred)
To do this, it's best to create an 'ImageDataService' service, where it get's kicked off at application start, and proceeds with building this array and taking whatever time it needs asynchronously without caring what view is showing or not. This service will be injected into the proper view or directive controller--perhaps where the current ng-repeat scope is.
Meanwhile, you also need to change the directives inside your ng-repeat to get the pre-built data from the array provided by ImageDataService rather than actually doing the calculation at view time. If the data for that directive is not ready, the directive will show something like 'loading...' otherwise, the directive will simply show the prebuilt images. This way, it doesn't matter when ng-repeat is triggered (i.e. its view is showing), because it will just show what are processed and ready at that point and the display the rest as 'loading...'.
METHOD 2 (I prefer this)
Alternatively, and maybe better, you can forego creating a pre-processed array in a service as in METHOD 1 and instead modify your directives to process their data asynchronously by invoking a service method that returns an asynchronous promise like this:
(code inside a controller)
var promise = ImageDataService.processImage(directiveData);
promise.then(function() {...set the directive image attributes..})
Needless to say, the ImageDataService.processImage() method needs to return a promise when it is done processing the data. The directive, as usual, will show 'loading...' until then. Also, although ImageDataService no longer needs to pre-populate its array mentioned in METHOD 1, it might be a good idea to save the processed images to a similar array anyway to serve as cache and not reprocess them needlessly. NOTE, in this case you don't need to have processImage() inside a service--but it is really good 'separation of concerns' practice to reserve the work of asynchronous data processing (ajax, etc) within a service which can be injected app-wide rather than within a controller.
Either of these 2 general tacks should work.

Would it make sense to use directive instead of filter to speed up performance?

It seems like angularjs 1.x filter is not recommended, with the reason given below:
http://blog.scalyr.com/2013/10/angularjs-1200ms-to-35ms/
Angular runs every single filter twice per $digest cycle once something has changed. This is some pretty heavy lifting. The first run is from the $$watchers detecting any changes, the second run is to see if there are further changes that need updated values.
I wonder if it make sense to either:
Use bind-once with filter
Write custom directive that ensures no additional watch is required?

Angular lookup value/display value

I have some data on a model that comes in the form of a code such as "US60" and "US70".
I need to take that value and show a display value such as "US 7day/60hour" and "US 8day/70hour". I'm not sure if there is any best practices way to do this in Angular, and I'm not having much luck googling it.
What I would do is have a service that I pass in type and value, and it would return a display value, but as with many things in Angular, since this is my first Angular project, I don't know if it's a good way to do it or not.
I'm just needing to use the display value in html such as {{settings.cycle}} I am already able to access the variable, but I want to show the display value, not the actual value.
If I am getting the gist of your question correctly, you have the value available but want to alter how it is displayed on screen right?
There are two main approaches to do this in Angular, using a directive or a filter.
A filter is basically like a pipe in Unix. You can alter a value before it is being displayed. For example:
{ username | uppercase } will transform the username into an all-caps username. Naturally, you can define your own filters for your use case. Filters are mostly used to transform single values. So for your case, a filter sounds best.
A directive is commonly used to create entire components on a page. For example: <user-profile-card></user-profile-card> would be transformed, using the directive, into the appropriate html/css/logic. So these are used often for larger transformations which involve logic, like server requests. Still these directives could also be used for very small components.
So for your case, although what you are actually want to do is not completely clear to me honestly, a filter seems to be your best shot ;)

AngularJS - Why is ng-bind faster than expressions?

From this question and this answer, it seems that using expressions will cause the value to be evaluated from scratch every time. But I've searched the documentation and tutorials, and I haven't found a reference for this statement.
In my mind, both are wrapped in a $watch() and so when the $digest() cycle runs it will see whether the value inside ng-bind or {{}} has changed.
On performance, why is ng-bind better than {{}} as has been suggested, and where's the reference?
Details like this aren't always available in the documentation - you have to read the source. I took a peek and it seems that (as of 2014-11-24) they both work in a very similar way. Both cause a single directive to be instantiated to change the value when needed (the curly interpolation directive is generated on the fly).
Both directives evaluate the expressions involved on every $digest just like everything else. The main difference is that while ng-bind doesn't do any further processing on the value, with curlies, the entire interpolated text is recalculated on every digest. Essentially a string is built using $interpolate and that is compared with the previous value (this happens within the bowels of $digest). Neither way will update the DOM if the value (either the plain value with ng-bind or the interpolated result with curlies) hasn't changed.
To me the accepted answer on that question is a more compelling reason to use ng-bind, i.e. you can use it to prevent a visible flash of the template tags before Angular loads and compiles them, without resorting to hacks like ng-cloak.
Depending on variables there may also be cases where curly interpolation is actually more performant. One situation I can think of is when using ng-bind instead of interpolation requires you to create a lot of otherwise redundant <span> elements, and that tips the scales in the other direction. An interpolation expression also causes a single watcher to be created for the entire string independent of how many variables you use, as opposed to ng-bind which creates one watcher for each instance.
But as always, don't optimize for performance early, and if you do, profile to find out which part really matters.
The major difference between ng-bind and {{}} is that ng-bind creates a watcher for variable passed to it(i.e. name as in above example), while curly brackets({{}}) will (store the entire expression in memory i.e. }perform dirty-checking and refreshing the expression in every digest cycle even if it is not required.
ng-bind will only apply when the value passed is changing actually.
for more details refer below link:
http://www.ufthelp.com/2015/11/difference-between-and-ng-bind-in.html

What are the main problems programmer should be aware of while using ng-repeat in AngularJS?

I am writing new directive that is going to use ng-repeat to create nested child's and more. What I have seen so far is there are all kind of problems using this great tool of angular. You get a great binding to data, but when data increases, you are going to suffer from very low performance and defects hard to be solve. This is making the all directive very hard to maintain and reuse.
So I wanted to ask all of you who have a lot of experience with AngularJS, what are the best things to be aware of in order to use it properly and not doing huge mistakes.
Did you ever think not using it and just make your own loop?
Be glad to hear your points.
Let’s quickly recap how we can use ng-repeats (along with optional filters):
<div ng-repeat="stock in ctrl.stocks | filter:someCondition">
</div>
We can also use ng-repeats to iterate over objects (In case you hadn’t known this):
<div ng-repeat="(key, stock) in ctrl.stocksMap | filter:someOtherCondition">
</div>
where stocksMap is an object map, where the key is the id of the stock, and the value is the individual stock object. One common misunderstanding now is how AngularJS creates and displays the UI, based on this ng-repeat. This is how AngularJS works under the covers (in a nutshell) when you use ng-repeat:
It iterates over each item in the array (or each key, value in the
object)
It runs each item via any filters that are present in our
expression, to check if it should be displayed or not
It calculates a hash value by which it identifies the object (which
is by reference by default)
It checks if it has already created a DOM element for the hash value
previously If so, it reuses it
If not, it creates a DOM element based on the ng-repeat template
All the DOM manipulations are taken and inserted in an optimal
manner into the actual DOM
A watch is added on the array, which triggers step 1 again if the
array undergoes any change
For More information you can refer this LINK

Resources