Anything similar to ChangeDetectionStrategy.OnPush in AngularJS 1? - javascript

Is there an equivalent to Angular's (v2+) ChangeDetectionStrategy.OnPush for AngularJS 1?
In other words, is there a way to restrict $digest cycles from re-evaluating scope inside certain components unless the component's $onChanges hook has just fired (meaning one of the bindings has been updated)? This could be built-in functionality into AngularJS or a third-party module.
Working with SPAs that have very large code bases (meaning it would take a year to upgrade to Angular2), it would certainly be nice to get some of those OnPush performance benefits today.

Related

Really slow change detection in hybrid Angular app

We have a hybrid AngularJS / Angular 8 app, and we keep constantly running into issues with really slow change detection between components from different versions of the framework. Until now we've only had this problem when using AngularJS components inside Angular components. The common case is having a new Angular 8 form that has some old AngularJS components in it, and with some specific AngularJS components it can take anywhere between ~2 to ~10 seconds for the changes made in the component to propagate to the Angular form and for form validations to run. The UI doesn't hang or anything, it stays responsive, but there just seems to be a varying delay in communications between the different versions of the framework. Other AngularJS components in the same form might work seamlessly. We haven't found out the root cause for it yet, but we have found one reliable workaround; use $timeout(() => $scope.apply()); in the AngularJS component, usually in the $onChanges-listener. This triggers change detection in Angular and removes the delay.
Now we're facing it with an Angular component that is used inside an AngularJS component. We have a new Angular component that essentially wraps an NG Bootstrap datepicker, and after selecting a date in the datepicker, there is a varying delay of several seconds (up to around 10 seconds) before the parent AngularJS form realizes that any changes were made. Angular's upgrade guide mentions that you can use NgZone.run() to manually trigger change detection when using downgradeModule() (which we are), but we haven't found a way to get it working. The documentation doesn't really go into detail how run() should be used, either. We also tried ChangeDetectorRef.detectChanges(), to no avail.
I tried passing the AngularJS parent component's $scope down to the Angular component and using setTimeout(() => $scope.$apply()); in the Angular component after emitting a change event with an EventEmitter, and that did work; the delay was gone. But obviously this is not something we want to use for real.
Any suggestions on how to eliminate the change detection delay between AngularJS / Angular 8 components, either by manually triggering change detection from an Angular component or some other way?
In the end we didn't find any other solution than the one described in the question: passing the AngularJS $scope as an input parameter to the Angular component and wrapping the event emissions in $scope.$apply(), i.e.
$scope.$apply(() => valueChange.emit(value));
Based on the Angular upgrade guide, this seems to be the only way to get it working when using downgradeModule().
Problems occur in AngularJS as it runs in cycles ($digset). That way, AngularJS can evaluate the changes between the model and the view.
In every $digest cycle, the watchers are executed. This is the phase where Angular evaluates the expressions that are attached to the view and re-renders them back to the user.
There are a lot of times when operations in the client should and need to be done outside of the “Angular world”, which means Angular is not aware of these changes and does not reflect the changes to the user. There are several methods to resolve this issue, one as you mentioned using $timeout, methods are:
$apply()
$timeout()
$digest()
$evalAsync()
$evalAsync() was first introduced in AngularJS 1.2.X, and for me, it’s the best method to use.
Before $evalAsync() was introduced, Officially answered by the Angular team, when you have issues with cycles and want to reflect changes from outside the “Angular world”, use $timeout().
After Angular has evolved and more users have experienced this known issue, the Angular team has created the $evalAsync(). This function will evaluate the expression during the current cycle or the next.
For more details: source

Performance impact of ngDoCheck, ngAfterViewChekedd and other alike angular lifehooks

What is the impact of the following two methods (and if others alike) on angular application's performance?
ngDoCheck
ngAfterViewChecked
As when implemented this two methods they keep on firing (continuously), and when used what one should take care of?

Knockout's purecomputed equivalent in Angular?

From my understanding of this article, (and please correct me if I'm wrong) Angular's two way binding model using $watch is equivalent to Knockout's computed observables.
According to the KnockoutJS documentation, pure computed observables prevent memory leaks and reduce CPU overhead. Does AngularJS have an equivalent?
I'm not very proficient with either Knockout or Angular but have used both very briefly. Now, lets say that I have an existing application using KnockbackJS which I want to move to AngularJS. Now I have the things like routing and templating covered, but What would I do for all the instances where purecomputed is being used?
AngularJS 1.x and KnockoutJS are similar, yet very different. Concerning your question, they are actually wildly different: Angular uses a digest cycle for change detection, where KnockoutJS uses a subscription-based approach under the cover.
Yes, watches in Angular look a lot like computeds from KnockoutJS, because they allow you to do a manual "subscription" which is checked during each digest cycle.
That is also where comparing apples and oranges starts to loose its potency. The difference between a computed and a pureComputed is a technical detail of KnockoutJS. AFAIK there is no direct equivalent of that in AngularJS, or perhaps you could argue that a watch is the equivalent.
Most likely you have an XY-problem, where you know how to solve X in KnockoutJS: with computeds and pureComputeds. Don't try to translate Y to AngularJS, but try to translate X to your new situation, and find an idiomatic way to solve that with AngularJS instead.

Components and directives in angular 1.5

The big feature changes in Angular 1.5 are surrounding the support of components.
component('myComponent', {
template: '<h1>Hello {{ $ctrl.getFullName() }}</h1>',
bindings: { firstName: '<', lastName: '<' },
controller: function() {
this.getFullName = function() {
return this.firstName + ' ' + this.lastName;
};
}
});
While this is all good, I am not sure how this differs from directives.
What are the benefits of using components over traditional custom directives? And are components in Angular 1.5 and Angular 2 the same?
The .component DOES NOT replaces .directive like #rek Żelechowski said.
So..
There’s nothing you can do with .component() that you can’t do with .directive().
It aims to simplify the way we create “components” – which roughly means UI directives.
When can/should you use it?
Clearly there are a few cases where you can’t/shouldn’t use it:
If you need the link function (though you rarely should)
If you want a template-less directive, e.g. ng-click that doesn’t have a template or separate scope
For all your other directives, this should work. And because it saves on boilerplate and less error-prone it’s nicer to use.
Despite of all new goodies, .component() can’t fully replace .directive().
The .component is now preferred way of writing code because it favors good practices and gives developers ability to write code like in angular 2 (similar to Web Components). Basically, when you write code using component, upgrading to angular 2 will be easier. Functionalities remains almost the same. You should use .component always when it is possible.
Changes (extract)
component is declared using object instead of function
simplified isolated scope using binding property
components are always with isolated scope
some bad practices will not be possible
simpler, easier to understand configuration
lifecycle hooks: ($onInit(), $onChanges(changesObj), $doCheck(), $onDestroy(), $postLink())
Awesome article is here:
https://toddmotto.com/exploring-the-angular-1-5-component-method
When not to use Components (from docs):
for directives that need to perform actions in compile and pre-link functions, because they aren't available
when you need advanced directive definition options like priority, terminal, multi-element
when you want a directive that is triggered by an attribute or CSS class, rather than an element.
I believe, that the best description you can find is official guide: https://docs.angularjs.org/guide/component. It covers all changes, reasons for changes and gives you deep understanding of the components.
EDIT 01-2020:
I don't work on ng1 code anymore since at least a year
At the point of writing response (01-2017), impression that they are going to replace directives in most scenarios was correct. I removed a word "replaced" from the answer in 06-2017, because it is was indeed misleading at that point in time. However, since 1.5 you should still prefer components over directives when possible.
Actually, you should prefer not to use AngularJS at all. It is now in LTS and basically, only errors will be fixed. No new features. Also, LTS ends on 01-07-2021.
https://docs.angularjs.org/misc/version-support-status#long-term-support
PS. Using component instead of directive makes the code easier to port to ngx in the future.
Directives are NOT replaced, they just have been changed for lots of various reasons that might be a bit too much to get into here. The angular docs explain them pretty well, so you can start looking at the documentation there:
https://docs.angularjs.org/guide/component
To get a better idea of what the differences between directives and components are, I find that its better to reference the Angular 2.0 documentation. Angular 1.5 gave us a bridge to 2.0 that 1.4 and prior did not have. One of the bigger changes is removing $scope, another is providing Components as a way to build things (which is HIGHLY used in Angular 2.0).
All in all the very meat of the change is that it prepares the 1.X world to migrate to the 2.X world. In that world there are Components (which are element level directives at their heart), structural directives and attribute directives. See the below links to help understand each (along with the link provided above).
http://learnangular2.com/components/
https://angular.io/docs/ts/latest/guide/structural-directives.html
https://angular.io/docs/ts/latest/guide/attribute-directives.html

After death of few Angular1 componets, The rest remain Same?

I am just curious to know, Is it like after the removal of few components like :
The rest off other components will remain same, because it is not mentioned in the image above
like:
Services,
Event (broadcast, emit, on)
run block
constant
config
And many others.
Hope the above question is valid, If so please give me idea about what is still remains , so that I feel easier in learning/adapting the new angular 2.
TypeScript:
I have seen the changes in class oriented block changes in typescript
like :
class MyComponent {
constructor() {
this.name = 'Max'
}
sayMyName() {
console.log('My name is', this.name)
}
}
Does that mean the commonly used DOM manipulation functions like
document.getElementBy
window object
And other things will same to an extent ?
Please give me some reference or idea about How much the Typescript has changed
Question 1:
The high-level abstraction is still the same (controllers, directives, services), but all the implementation details changed as the framework is rewritten in TypeScript.
For example, angular modules will be ditched in favour of ES6 native ones, which means run block, constant and config will not be relevant. Howevver, since they're keeping dependency injection, some way of configuration must exist, so whatever you can do in config and run will still be doable.
Question 2:
You probably confused TypeScript with JavaScript. The former has always had a syntax like that (so will the next version of JavaScript (ES6/harmony) to some extent).
However, the language change does not affect how you use the framework as TypeScript is supposed to be a superset of JavaScript, so most valid JS is also valid TS. You do not have to use features specific to TypeScript if you don't want to.
Based upon my understandings of how angular 2 is coming together this is how I see the other pieces fitting together.
Disclaimers
I am not a developer on the project, just a guy who is trying to keep up with the project as it is being developed.
The current state of angular 2 is alpha/developer preview and can/will change as development progresses
Overview
As angular 1.* progressed in its maturity there was a clear movement to utilizing conventional JavaScript patterns (see controllerAs, bindToController, no global controllers) and by following that convention your code for angular 1.* will be closer aligned to angular 2. The other movement that will assist you as you prepare for angular 2 is to think about your application in the idea of components (directive + controller with services injected in).
Services
These are classes that can be injected into components
Events (broadcast/emit)
These are a pub/sub implementation based upon the inherited $scope model which is not going to be present in angular 2, so another eventing model will need implemented. I have not heard this discussed from the angular team, so either be patient or pick another pub/sub model to implement.
Run block
With angular 2 being component based when the app is run is a direct correlation with the constructor of the root component (the one being bootstrapped)
Constants
Constants in angular 1 are just values that can be injected into other components, nothing has changed here and values can be injected into components in angular 2.
Config
With the angular module system going away in lieu of ES6 modules the idea of configuration (initializing values for a service) can be done in the constructor of the service. Also, angular 2 is going to support the idea of lazy loading additional components so configuration can be done later as well as upon application start
references
angular 2 project home page https://angular.io/
ng-conf videos https://www.youtube.com/user/ngconfvideos
angular 2 todo demo https://www.youtube.com/watch?v=uD6Okha_Yj0
angular 2 forms intro https://www.youtube.com/watch?v=4C4bmDOV5hk
getting started video https://www.youtube.com/watch?v=HmWm21cCAXM

Categories

Resources