How to Make Which Repeating Data Again Get Repeted Values in Angularjs

Single page apps need the front-end developers to go better software engineers. CSS and HTML are not the biggest business anymore, in fact, there is no longer just a single business organization. The front-end developer needs to handle XHRs, awarding logic (models, views, controllers), performance, animations, styles, structure, SEO, and integration with external services. The result which emerges from all those combined is the User Experience (UX) which should e'er be prioritized.

AngularJS is a very powerful framework. It is the third most starred repository on GitHub. Information technology is not difficult to first using, but the goals that it is intended to accomplish demand comprehension. No longer can AngularJS developers ignore memory consumption, because it will not reset on navigation anymore. This is the vanguard of web development. Permit's embrace information technology!

Common AngularJS mistakes

Mutual Error #ane: Accessing The Telescopic Through The DOM

In that location are a few optimization tweaks recommended for product. I of them is disabling debug info.

DebugInfoEnabled is a setting which defaults to truthful, and allows for scope admission through DOM nodes. If yous want to attempt that through the JavaScript console, select a DOM element and access its scope with:

          athwart.chemical element(document.body).scope()                  

It can exist useful even when not using jQuery with its CSS, just should not be used outside of the console. The reason being that when $compileProvider.debugInfoEnabled is set to false, calling .scope() on a DOM node volition return undefined.

That is 1 of the few recommended options for product.

Please note that yous can still access the scope through the panel, even when on production. Call angular.reloadWithDebugInfo() from the console and the app volition do just that.

Mutual Fault #2: Non Having a Dot In At that place

Yous probably have read that if you were not having a dot in your ng-model, you were doing it incorrect. When it regards inheritance, that statement is often truthful. Scopes take a prototypal model of inheritance, typical to JavaScript, and nested scopes are common to AngularJS. Many directives create kid scopes such as ngRepeat, ngIf, and ngController. When resolving a model, the lookup starts on the current telescopic and goes through every parent scope, all the way to $rootScope.

Simply, when setting a new value, what happens depends on what kind of model (variable) we want to alter. If the model is a primitive, the child scope will simply create a new model. Merely if the alter is to a property of a model object, the lookup on parent scopes volition find the referenced object and change its actual holding. A new model would non exist attack the current scope, so no masking would occur:

          part MainController($scope) {   $scope.foo = 1;   $telescopic.bar = {innerProperty: 2}; }  angular.module('myApp', []) .controller('MainController', MainController);                  
          <div ng-controller="MainController">   <p>OUTER SCOPE:</p>   <p>{{ foo }}</p>   <p>{{ bar.innerProperty }}</p>   <div ng-if="foo"> <!— ng-if creates a new telescopic —>     <p>INNER Scope</p>     <p>{{ foo }}</p>     <p>{{ bar.innerProperty }}</p>     <button ng-click="foo = 2">Set primitive</push button>     <push button ng-click="bar.innerProperty = iii">Mutate object</button>   </div> </div>                  

Clicking the button labelled "Set up primitive" volition set foo in the inner telescopic to 2, but will non change foo in the outer scope.

Clicking the button labelled "Alter object" volition modify the bar property from the parent telescopic. Since at that place is no variable on the inner scope, no shadowing will happen, and the visible value for bar will be iii in both scopes.

Some other way to practise this is to leverage the fact that the parent scopes and the root Scope are referenced from every scope. The $parent and $root objects can exist used to admission the parent scope and $rootScope, respectively, directly from the view. It may be a powerful way, merely I am non a fan of it due to the problem with targeting a particular telescopic up the stream. In that location is another manner to gear up and access properties specific to a telescopic - using the controllerAs syntax.

Common Mistake #3: Not Using controllerAs Syntax

The culling and most efficient style to assign models to use a controller object instead of the injected $scope. Instead of injecting scope, we can define models similar this:

          role MainController($scope) {   this.foo = 1;   var that = this;   var setBar = function () {     // that.bar = {someProperty: 2};     this.bar = {someProperty: 2};   };   setBar.call(this);   // at that place are other conventions:    // var MC = this;   // setBar.call(this); when using 'this' inside setBar() }                  
          <div>   <p>OUTER SCOPE:</p>   <p>{{ MC.foo }}</p>   <p>{{ MC.bar.someProperty }}</p>   <div ng-if="test1">     <p>INNER Scope</p>     <p>{{ MC.foo }}</p>     <p>{{ MC.bar.someProperty }}</p>     <push ng-click="MC.foo = iii">Modify MC.foo</button>     <push button ng-click="MC.bar.someProperty = 5">Change MC.bar.someProperty</button>   </div> </div>                  

This is much less disruptive. Particularly when there are many nested scopes, equally can be the case with nested states.

There is more than to the controllerAs syntax.

Common Mistake #4: Not Fully Utilising The controllerAs Syntax

There are a few caveats with how the controller object is exposed. It is basically an object attack the controller's scope, just like a normal model.

If you need to watch a property of the controller object, you lot tin watch a function but you are non required to. Here is an example:

          function MainController($scope) {   this.championship = 'Some title';   $scope.$scout(angular.bind(this, function () {     return this.title;   }), role (newVal, oldVal) {     // handle changes   }); }                  

Information technology is easier to just do:

          function MainController($scope) {   this.championship = 'Some title';   $scope.$lookout man('MC.championship', function (newVal, oldVal) {     // handle changes   }); }                  

Meaning that also down the telescopic chain, you lot could access MC from a kid controller:

          function NestedController($scope) {   if ($scope.MC && $scope.MC.title === 'Some championship') {     $telescopic.MC.title = 'New title';   } }                  

Nonetheless, to be able to do that you demand to be consequent with the acronym you lot use for controllerAs. There are at least three ways to ready information technology. You already saw the first one:

          <div ng-controller="MainController as MC">    … </div>                  

However, if you use ui-router, specifying a controller that way is prone to error. For states, controllers should exist specified in the country configuration:

          angular.module('myApp', []) .config(part ($stateProvider) {   $stateProvider   .state('principal', {     url: '/',     controller: 'MainController as MC',     templateUrl: '/path/to/template.html'   }) }). controller('MainController', role () { … });                  

At that place is some other style to comment:

          (…) .country('master', {   url: '/',   controller: 'MainController',   controllerAs: 'MC',   templateUrl: '/path/to/template.html' })                  

You lot can do the aforementioned in directives:

          function AnotherController() {   this.text = 'abc'; }  function testForToptal() {   render {     controller: 'AnotherController as AC',     template: '<p>{{ Air-conditioning.text }}</p>'   }; }  angular.module('myApp', []) .controller('AnotherController', AnotherController) .directive('testForToptal', testForToptal);                  

The other style to annotate is valid also, although less curtailed:

          role testForToptal() {   render {     controller: 'AnotherController',     controllerAs: 'AC',     template: '<p>{{ AC.text }}</p>'   }; }                  

Mutual Error #v: Non Using Named Views With UI-ROUTER For Power"

The de facto routing solution for AngularJS has been, until now, the ui-router. Removed from core sometime ago, ngRoute module, was besides bones for more sophisticated routing.

At that place is a new NgRouter on information technology'southward way, but the authors still consider it as well early for production. When I am writing this, the stable Angular is 1.three.xv, and ui-router rocks.

The main reasons:

  • awesome country nesting
  • route abstraction
  • optional and required parameters

Here I will cover land nesting to avert AngularJS errors.

Think of this equally a circuitous yet standard employ case. There is an app, which has a homepage view and a production view. The product view has three separate sections: the intro, the widget, and the content. We want the widget to persist and non reload when switching betwixt state. Just the content should reload.

Consider the following HTML product alphabetize page construction:

          <body>   <header>     <!-- SOME STATIC HEADER CONTENT -->   </header>    <section class="principal">     <div grade="folio-content">      <div class="row">       <div form="col-xs-12">         <section class="intro">           <h2>SOME PRODUCT SPECIFIC INTRO</h2>         </section>       </div>     </div>      <div form="row">       <div class="col-xs-3">         <section class="widget">           <!-- some widget, which should never reload -->         </section>       </div>       <div form="col-xs-nine">         <section class="content">           <div class="product-content">           <h2>Production title</h2>           <span>Context-specific content</span>         </div>         </department>       </div>     </div>    </div>    </section>    <footer>     <!-- SOME STATIC HEADER CONTENT -->   </footer>  </body>                  

This is something we could get from the HTML coder, and now need to split up information technology into files and states. I generally go with the convention that there is an abstract Primary country, which keeps the global data if needed. Use that instead of $rootScope. The Main state will as well keep static HTML that is required on every folio. I proceed index.html clean.

          <!— index.html —> <body>   <div ui-view></div> </body>                  
          <!— main.html —> <header>   <!-- SOME STATIC HEADER CONTENT --> </header>  <section form="main">   <div ui-view></div> </section>  <footer>   <!-- SOME STATIC HEADER CONTENT --> </footer>                  

Then permit's run into the production index page:

          <div form="page-content">    <div class="row">     <div class="col-xs-12">       <section grade="intro">         <div ui-view="intro"></div>       </department>     </div>   </div>    <div form="row">     <div class="col-xs-3">       <section class="widget">         <div ui-view="widget"></div>       </section>     </div>     <div class="col-xs-9">       <section class="content">         <div ui-view="content"></div>       </department>     </div>   </div>  </div>                  

As you can meet, the product index page has three named views. One for the intro, one for the widget, and 1 for the product. Nosotros meet the specs! So now permit's set up routing:

          function config($stateProvider) {   $stateProvider     // Master Abstruse STATE, ALWAYS ON     .state('main', {       abstruse: truthful,       url: '/',       controller: 'MainController as MC',       templateUrl: '/routing-demo/chief.html'     })     // A Unproblematic HOMEPAGE     .land('main.homepage', {       url: '',       controller: 'HomepageController equally HC',       templateUrl: '/routing-demo/homepage.html'     })     // THE Above IS ALL GOOD, HERE IS TROUBLE     // A Circuitous Production Page     .state('principal.product', {       abstract: truthful,       url: ':id',       controller: 'ProductController every bit PC',       templateUrl: '/routing-demo/product.html',     })     // Production DEFAULT SUBSTATE     .state('main.production.alphabetize', {       url: '',       views: {         'widget': {           controller: 'WidgetController as PWC',           templateUrl: '/routing-demo/widget.html'          },         'intro': {           controller: 'IntroController as Picture show',           templateUrl: '/routing-demo/intro.html'          },         'content': {           controller: 'ContentController as PCC',           templateUrl: '/routing-demo/content.html'         }       }     })     // PRODUCT DETAILS SUBSTATE     .land('main.product.details', {       url: '/details',       views: {         'widget': {           controller: 'WidgetController as PWC',           templateUrl: '/routing-demo/widget.html'          },         'content': {           controller: 'ContentController as PCC',           templateUrl: '/routing-demo/content.html'         }       }     }); }  angular.module('articleApp', [   'ui.router' ]) .config(config);                  

That would be the first approach. Now, what happens when switching between main.product.index and chief.production.details? The content and widget get reloaded, simply we only desire to reload the content. This was problematic, and developers actually created routers that would support just that functionality. One of the names for this was sticky views. Fortunately, ui-router supports that out of the box with absolute named view targeting.

          // A Circuitous PRODUCT PAGE // WITH NO More TROUBLE .state('principal.product', {   abstruse: true,   url: ':id',   views: {     // TARGETING THE UNNAMED VIEW IN MAIN.HTML     '@chief': {       controller: 'ProductController every bit PC',       templateUrl: '/routing-demo/product.html'      },     // TARGETING THE WIDGET VIEW IN Production.HTML     // BY DEFINING A Child VIEW ALREADY HERE, WE ENSURE IT DOES NOT RELOAD ON CHILD Country Change     'widget@main.product': {       controller: 'WidgetController as PWC',       templateUrl: '/routing-demo/widget.html'      }   } }) // Product DEFAULT SUBSTATE .state('main.product.alphabetize', {   url: '',   views: {     'intro': {       controller: 'IntroController as PIC',       templateUrl: '/routing-demo/intro.html'      },     'content': {       controller: 'ContentController as PCC',       templateUrl: '/routing-demo/content.html'     }   } }) // PRODUCT DETAILS SUBSTATE .state('main.product.details', {   url: '/details',   views: {     'content': {       controller: 'ContentController as PCC',       templateUrl: '/routing-demo/content.html'     }   } });                  

By moving the state definition to the parent view, which besides is abstract, we can preserve the child view from reloading when switching urls which normally affects that child's siblings. Of class, the widget could exist a simple directive. But the point is, it could also be another complex nested state.

In that location is another way to do this through the utilise of $urlRouterProvider.deferIntercept(), merely I think that using state configuration is actually better. If yous are interested in intercepting routes, I wrote a small tutorial on StackOverflow.

Common Error #six: Declaring Everything In The Athwart Globe Using Anonymous Functions

This fault is of a lighter calibre, and is more than a question of style than avoiding AngularJS error messages. You may take previously noticed that I seldom pass anonymous functions to angular internal's declarations. I ordinarily merely define a function showtime and so pass it in.

This regards more than just functions. I got this approach from reading style guides, specially Airbnb's and Todd Motto's. I believe in that location are several advantages and near no drawbacks to information technology.

Showtime of all, you can manipulate and mutate your functions and objects much easier if they are assigned to a variable. Secondly, the lawmaking is cleaner and tin can exist easily dissever into files. That ways maintainability. If you don't want to pollute the global namespace, wrap every file in IIFEs. The 3rd reason is testability. Consider this example:

          'use strict';  function yoda() {    var privateMethod = function () {     // this part is not exposed   };    var publicMethod1 = function () {     // this function is exposed, simply it's internals are non exposed     // some logic...   };    var publicMethod2 = function (arg) {     // THE Beneath Phone call CANNOT Exist SPIED ON WITH JASMINE     publicMethod1('someArgument');   };    // IF THE LITERAL IS RETURNED THIS Manner, It CAN'T Be REFERRED TO FROM Inside   return {     publicMethod1: function () {       return publicMethod1();     },     publicMethod2: function (arg) {       return publicMethod2(arg);     }   }; }  angular.module('app', []) .manufactory('yoda', yoda);                  

So at present we could mock the publicMethod1, merely why should we practise that since information technology is exposed? Wouldn't it be easier simply to spy on the existing method? All the same, the method is actually another function - a thin wrapper. Take a wait at this approach:

          function yoda() {    var privateMethod = function () {     // this function is not exposed   };    var publicMethod1 = function () {     // this function is exposed, simply it's internals are not exposed     // some logic...   };    var publicMethod2 = office (arg) {     // the below telephone call cannot be spied on     publicMethod1('someArgument');      // BUT THIS ONE CAN!     hostObject.publicMethod1('aBetterArgument');   };    var hostObject = {     publicMethod1: part () {       return publicMethod1();     },     publicMethod2: part (arg) {       return publicMethod2(arg);     }   };    render hostObject; }                  

This is non only nigh fashion, since in effect the code is more reusable and idiomatic. The developer gets more expressive ability. Splitting all code into cocky-contained blocks just makes information technology easier.

Mutual Error #vii: Doing Heavy Processing In Angular AKA Using Workers

In some scenarios, it may be required to process a big array of complex objects by passing them through a set of filters, decorators, and finally a sorting algorithm. 1 use case is when the app should work offline or where the performance of displaying data is fundamental. And since JavaScript is unmarried-threaded, information technology is relatively easy to freeze the browser.

It is also like shooting fish in a barrel to avert it with web workers. There don't seem to be any pop libraries that handle that specifically for AngularJS. It might be for the best though, since the implementation is easy.

Showtime, allow's setup the service:

          role scoringService($q) {      var scoreItems = office (items, weights) {     var deferred = $q.defer();     var worker = new Worker('/worker-demo/scoring.worker.js');     var orders = {       items: items,       weights: weights     };     worker.postMessage(orders);     worker.onmessage = part (e) {       if (e.data && e.data.gear up) {         deferred.resolve(e.data.items);       }     };      render deferred.promise;   };   var hostObject = {     scoreItems: function (items, weights) {       return scoreItems(items, weights);     }   };    render hostObject;  }  athwart.module('app.worker') .factory('scoringService', scoringService);                  

Now, the worker:

          'use strict';  function scoringFunction(items, weights) {   var itemsArray = [];   for (var i = 0; i < items.length; i++) {     // some heavy processing     // itemsArray is populated, etc.   }    itemsArray.sort(function (a, b) {     if (a.sum > b.sum) {       return -1;     } else if (a.sum < b.sum) {       return 1;     } else {       return 0;     }   });    return itemsArray; }  cocky.addEventListener('message', function (due east) {   var reply = {     gear up: true   };   if (e.data && e.data.items && eastward.data.items.length) {     answer.items = scoringFunction(e.data.items, east.information.weights);   }   self.postMessage(reply); }, false);                  

Now, inject the service as usual and treat scoringService.scoreItems() every bit you would any service method that returns a promise. The heavy processing will be carried out on a separate thread, and no harm will exist done to the UX.

What to look out for:

  • there does non seem to be a general rule for how many workers to spawn. Some developers merits that 8 is a practiced number, but use an online figurer and suit yourself
  • check compatibility with older browsers
  • I come across an issue when passing the number 0 from the service to the worker. I applied .toString() on the passed belongings, and it worked correctly.

Common Mistake #eight: Overusing And Misunderstanding Resolves

Resolves add actress fourth dimension to the loading of the view. I believe that high performance of the forepart-end app is our primary goal. It should not exist a problem to return some parts of the view while the app waits for the data from the API.

Consider this setup:

          function resolve(index, timeout) {   return {     data: function($q, $timeout) {       var deferred = $q.defer();       $timeout(function () {         deferred.resolve(console.log('Data resolve called ' + index));       }, timeout);       render deferred.promise;     }   }; }  function configResolves($stateProvide) {   $stateProvider     // Main ABSTRACT STATE, E'er ON     .state('chief', {       url: '/',       controller: 'MainController equally MC',       templateUrl: '/routing-demo/main.html',       resolve: resolve(ane, 1597)     })     // A Circuitous PRODUCT Folio     .state('main.product', {       url: ':id',         controller: 'ProductController every bit PC',       templateUrl: '/routing-demo/production.html',       resolve: resolve(2, 2584)     })     // PRODUCT DEFAULT SUBSTATE     .state('main.product.index', {       url: '',       views: {         'intro': {           controller: 'IntroController as Motion-picture show',           templateUrl: '/routing-demo/intro.html'         },         'content': {           controller: 'ContentController as PCC',           templateUrl: '/routing-demo/content.html'         }       },       resolve: resolve(3, 987)     }); }                  

The panel output will be:

          Data resolve chosen 3 Information resolve called 1 Data resolve chosen ii Principal Controller executed Product Controller executed Intro Controller executed                  

Which basically means that:

  • The resolves are executed asynchronously
  • We can't rely on an order of execution (or at least need to flex quite a bit)
  • All the states are blocked until all resolves do their thing, even if they are non abstruse.

This means that earlier the user sees whatever output, he/she must look for all the dependencies. We demand to have that information, sure, okay. If it absolutely necessary to have it earlier the view, put it in a .run() block. Otherwise, just make the phone call to the service from the controller and handle the one-half-loaded country gracefully. Seeing piece of work in progress - and the controller is already executed, and so it really is progress - is better than having the app stall.

Mutual Error #9: Not Optimizing The App - Iii Examples

a) Causing likewise many digest loops, such equally attaching sliders to models

This is a general trouble that can consequence in AngularJS errors, but I volition discuss it at the example of sliders. I was using this slider library, angular range slider, because I needed the extended functionality. That directive has this syntax in the minimal version:

          <body ng-controller="MainController as MC">   <div range-slider      min="0"      max="MC.maxPrice"      pin-handle="min"      model-max="MC.price"   >   </div> </torso>                  

Consider the following code in the controller:

          this.maxPrice = '100'; this.toll = '55';  $scope.$watch('MC.price', function (newVal) {   if (newVal || newVal === 0) {     for (var i = 0; i < 987; i++) {       console.log('ALL YOUR BASE ARE Vest TO United states of america');     }   } });                  

So that works slow. The casual solution would be to set a timeout on the input. Merely that is non e'er handy, and sometimes we don't actually want to delay the actual model alter in all cases.

So we will add together a temporary model spring to alter the working model on timeout:

          <body ng-controller="MainController as MC">   <div range-slider      min="0"      max="MC.maxPrice"      pivot-handle="min"      model-max="MC.priceTemporary"   >   </div> </trunk>                  

and in the controller:

          this.maxPrice = '100'; this.price = '55'; this.priceTemporary = '55';  $telescopic.$watch('MC.price', function (newVal) {   if (!isNaN(newVal)) {     for (var i = 0; i < 987; i++) {       console.log('ALL YOUR BASE ARE Belong TO US');     }   } });  var timeoutInstance; $scope.$watch('MC.priceTemporary', office (newVal) {   if (!isNaN(newVal)) {     if (timeoutInstance) {       $timeout.cancel(timeoutInstance);     }      timeoutInstance = $timeout(function () {       $scope.MC.cost = newVal;     }, 144);        } });                  

b) Not using $applyAsync

AngularJS does not have a polling mechanism to call $digest(). It is merely executed because we employ the directives (e.m. ng-click, input), services ($timeout, $http), and methods ($scout) which evaluate our code and telephone call a digest later.

What .$applyAsync() does is information technology delays the resolution of expressions until the adjacent $digest() bike, which is triggered later on a 0 timeout, which actually is ~10ms.

There are 2 ways to utilize applyAsync now. An automated manner for $http requests, and a manual way for the residuum.

To brand all http requests that render in around the same time resolve in one digest, practise:

          mymodule.config(function ($httpProvider) {   $httpProvider.useApplyAsync(true); });                  

The manual way shows how information technology really works. Consider some function that runs on the callback to a vanilla JS event listener or a jQuery .click(), or some other external library. After it executes and changes models, if yous didn't already wrap information technology in an $use() you need to call $telescopic.$root.$digest() ($rootScope.$digest()), or at least $scope.$assimilate(). Otherwise, yous will see no modify.

If you do that multiple times in 1 flow, it might showtime running ho-hum. Consider calling $telescopic.$applyAsync() on the expressions instead. It will set just call 1 digest cycle for all of them.

c) Doing heavy processing of images

If you lot experience bad performance, you tin investigate the reason by using the Timeline from Chrome Developer Tools. I will write more than about this tool in mistake #17. If your timeline graph is dominated with the colour green subsequently recording, your performance issues may be related to processing of images. This is not strictly related to AngularJS, merely may happen on top of AngularJS functioning issues (which would exist mostly yellowish on the graph). As front-cease engineers, nosotros need to think about the complete end project.

Take a moment to assess:

  • Do you use parallax?
  • Do y'all have several layers of content overlapping one some other?
  • Practise you move your images around?
  • Do you scale images (e.g. with background-size)?
  • Do you resize images in loops, and perhaps cause assimilate loops on resize?

If you answered "yep" to at least three of the higher up, consider easing it. Perchance you can serve various image sizes and not resize at all. Maybe yous could add the "transform: translateZ(0)" force GPU processing hack. Or utilize requestAnimationFrame for handlers.

Common Error #ten: jQuerying It - Detached DOM Tree

Many times you probably hear that it's non recommended to use jQuery with AngularJS, and that it should be avoided. It is imperative to empathize the reason behind these statements. There are at least three reasons, as far every bit I can run into, but none of them are actual blockers.

Reason 1: When you lot execute jQuery lawmaking, y'all need to call $digest() yourself. For many cases, there is an AngularJS solution which is tailored for AngularJS and can be of amend use inside Angular than jQuery (eastward.one thousand. ng-click or the event system).

Reason two: The method of idea about building the app. If y'all have been calculation JavaScript to websites, which reload when navigating, you did not have to worry about memory consumption too much. With unmarried-page apps, you do have to worry. If you don't make clean upwards, users who spend more a few minutes on your app may experience growing performance issues.

Reason 3: Cleaning up is non really the easiest thing to do and analyze. In that location is no fashion to call a garbage collector from the script (in the browser). You may cease up with detached DOM copse. I created an example (jQuery is loaded in index.html):

          <section>   <exam-for-toptal></test-for-toptal>   <button ng-click="MC.removeDirective()">remove directive</button> </section>                  
          part MainController($rootScope, $scope) {   this.removeDirective = office () {     $rootScope.$emit('destroyDirective');   }; }  office testForToptal($rootScope, $timeout) {   return {     link: function (scope, element, attributes) {        var destroyListener = $rootScope.$on('destroyDirective', function () {         scope.$destroy();       });        // calculation a timeout for the DOM to become ready       $timeout(function () {         telescopic.toBeDetached = element.find('p');       });        scope.$on('$destroy', function () {         destroyListener();         element.remove();       });     },     template: '<div><p>I AM DIRECTIVE</p></div>'   }; }  angular.module('app', []) .controller('MainController', MainController) .directive('testForToptal', testForToptal);                  

This is a simple directive that outputs some text. There is a button below it, which will simply destroy the directive manually.

So when the directive is removed, there remains a reference to the DOM tree in scope.toBeDetached. In chrome dev tools, if you access the tab "profiles" and and then "take heap snapshot", y'all will see in the output:

You can alive with a few, but it is bad if you have a ton. Especially if for some reason, like in the example, y'all store it on the telescopic. The whole DOM will be evaluated on every assimilate. The problematic discrete DOM tree is the i with 4 nodes. Then how tin this be solved?

          telescopic.$on('$destroy', role () {    // setting this model to null   // will solve the problem.   scope.toBeDetached = cypher;    destroyListener();   chemical element.remove(); });                  

The discrete DOM tree with 4 entries is removed!

In this example, the directive uses the same scope, and stores the DOM chemical element on the scope. Information technology was easier for me to demonstrate information technology that way. It does not always get that bad, equally y'all could shop it in a variable. However, it would nonetheless accept up retention if any closure that had referenced that variable or any other from the aforementioned function telescopic lived on.

Mutual Fault #eleven: Overusing Isolated Scope

Whenever you need a directive that you know volition be used in a single place, or which you don't expect to conflict with any environment it is used in, there is no demand to use isolated scope. Lately, there is a tendency to create reusable components, simply did yous know that cadre angular directives don't use isolated scope at all?

In that location are two main reasons: you can't apply two isolated scope directives to an element, and you may encounter bug with nesting / inheritance / effect processing. Especially regarding transclusion - the effects may not be what you expect.

Then this would fail:

          <p isolated-scope-directive some other-isolated-telescopic-directive ng-if="MC.quux" ng-repeat="q in MC.quux"></p>                  

And even if you use just one directive, yous volition notice that neither the isolated scope models nor events broadcasted in isolatedScopeDirective volition not exist bachelor to AnotherController. That being sorry, you can flex and utilize transclusion magic to brand it work - but for most use cases, there is no need to isolate.

          <p isolated-scope-directive ng-if="MC.quux" ng-repeat="q in MC.quux">   <div ng-controller="AnotherController">     … the isolated scope is not available hither, await: {{ isolatedModel }}   </div> </p>                  

Then, two questions now:

  1. How tin can yous process parent scope models in a same-telescopic directive?
  2. How tin can y'all instantiate new model values?

There are 2 ways, in both of them you pass values to attributes. Consider this MainController:

          role MainController($interval) {   this.foo = {     bar: 1   };   this.baz = 1;   var that = this;   $interval(function () {     that.foo.bar++;   }, 144);    $interval(office () {     that.baz++;   }, 144);    this.quux = [1,2,3]; }                  

That controls this view:

          <body ng-controller="MainController as MC">    <div class="cyan-surface">     <h1 fashion="font-size: 21px;">Attributes examination</h1>     <test-directive watch-attribute="MC.foo" detect-aspect="electric current index: {{ MC.baz }}"></examination-directive>   </div>  </trunk>                  

Notice that "sentinel-attribute" is not interpolated. It all works, due to JS magic. Here is the directive definition:

          role testDirective() {   var postLink = function (scope, element, attrs) {     scope.$picket(attrs.watchAttribute, part (newVal) {       if (newVal) {         // take a look in the console         // nosotros can't use the attribute directly         console.log(attrs.watchAttribute);          // the newVal is evaluated, and it can be used         scope.modifiedFooBar = newVal.bar * ten;       }     }, truthful);      attrs.$observe('observeAttribute', role (newVal) {       scope.observed = newVal;     });   };    return {     link: postLink,     templateUrl: '/attributes-demo/test-directive.html'   }; }                  

Find that attrs.watchAttribute is passed into telescopic.$watch() without the quotation marks! That means what was actually passed to $picket was the string MC.foo! It does piece of work, even so, because any string passed into $sentry() gets evaluated against the scope and MC.foo is available on the scope. That is too the most common mode that attributes are watched in AngularJS core directives.

See the lawmaking on github for the template, and look into $parse and $eval for even more than awesomeness.

Mutual Fault #12: Not Cleaning Up After Yourself - Watchers, Intervals, Timeouts And Variables

AngularJS does some piece of work on your behalf, simply not all. The following need to exist manually cleaned upwardly:

  • Any watchers that are not bound to the current scope (e.g. bound to $rootScope)
  • Intervals
  • Timeouts
  • Variables referencing DOM in directives
  • Dodgy jQuery plugins, e.g. those that don't have handlers reacting to the JavaScript $destroy issue

If y'all don't do that manually, you will see unexpected behaviour and memory leaks. Even worse - these volition non be instantly visible, but they volition pitter-patter upwards eventually. Murphy'southward law.

Amazingly, AngularJS provides handy ways to deal with all of those:

          function cleanMeUp($interval, $rootScope, $timeout) {   var postLink = part (scope, element, attrs) {     var rootModelListener = $rootScope.$watch('someModel', role () {       // do something     });      var myInterval = $interval(part () {       // practise something in intervals     }, 2584);      var myTimeout = $timeout(function () {       // defer some activeness here     }, 1597);      scope.domElement = element;      $timeout(function () {       // calling $destroy manually for testing purposes       telescopic.$destroy();     }, 987);      // here is where the cleanup happens     scope.$on('$destroy', function () {       // disable the listener       rootModelListener();        // cancel the interval and timeout       $interval.cancel(myInterval);       $timeout.cancel(myTimeout);        // nullify the DOM-bound model       scope.domElement = nix;     });      element.on('$destroy', function () {       // this is a jQuery result       // clean up all vanilla JavaScript / jQuery artifacts here        // respectful jQuery plugins have $destroy handlers,       // that is the reason why this event is emitted...       // follow the standards.     });    };                  

Detect the jQuery $destroy event. It is chosen like the AngularJS one, just it is handled separately. Telescopic $watchers will not react to the jQuery event.

Common Mistake #13: Keeping Too Many Watchers

This should be quite simple now. There is one affair to understand here: $digest(). For every binding {{ model }}, AngularJS creates a watcher. On every digest stage, each such binding is evaluated and compared against the previous value. That is called dirty-checking, and that's what $digest does. If the value changed since the terminal check, the watcher callback is fired. If that watcher callback modifies a model ($telescopic variable), a new $digest bicycle is fired (upwardly to a maximum of 10) when an exception is thrown.

Browsers don't accept issues even with thousands of bindings, unless the expressions are circuitous. The common reply for "how many watchers are ok to have" is 2000.

So, how tin we limit the number of watchers? By not watching scope models when we don't expect them to alter. It is fairly easy onwards from AngularJS one.3, since i-time bindings are in core now.

          <li ng-echo="detail in ::vastArray">{{ ::detail.velocity }}</li>                  

Subsequently vastArray and item.velocity are evaluated one time, they will never change once more. Y'all can notwithstanding apply filters to the assortment, they will work just fine. It is merely that the assortment itself will not be evaluated. In many cases, that is a win.

Mutual Mistake #14: Misunderstanding The Assimilate

This AngularJS error was already partly covered in mistakes 9.b and in thirteen. This is a more thorough caption. AngularJS updates DOM as a result of callback functions to watchers. Every binding, that is the directive {{ someModel }} sets upwards watchers, but watchers are likewise set for many other directives like ng-if and ng-repeat. Just take a wait at the source lawmaking, it is very readable. Watchers can also be set manually, and you lot have probably done that at least a few times yourself.

$watch()ers are bound to scopes. $Watchers can have strings, which are evaluated confronting the telescopic that the $picket() was jump to. They tin also evaluate functions. And they also take callbacks. So, when $rootScope.$assimilate() is called, all the registered models (that is $scope variables) are evaluated and compared against their previous values. If the values don't match, the callback to the $sentinel() is executed.

It is important to understand that fifty-fifty though a model'southward value was changed, the callback does not fire until the adjacent digest phase. It is called a "stage" for a reason - it can consist of several digest cycles. If only a watcher changes a scope model, another digest cycle is executed.

But $digest() is not polled for. Information technology is called from core directives, services, methods, etc. If you lot change a model from a custom function that does not phone call .$apply, .$applyAsync, .$evalAsync, or anything else that eventually calls $digest(), the bindings will not be updated.

By the fashion, the source code for $digest() is actually quite complex. Information technology is nevertheless worth reading, as the hilarious warnings brand upwards for it.

Common Fault #15: Not Relying On Automation, Or Relying On Information technology Too Much

If you follow the trends within front end development and are a bit lazy - like me - and then yous probably effort to not practise everything by mitt. Keeping rails of all your dependencies, processing sets of files in unlike ways, reloading the browser later on every file save - there is a lot more to developing than simply coding.

And so you may be using bower, and perhaps npm depending on how you serve your app. At that place is a chance that yous may be using grunt, gulp, or brunch. Or bash, which also is cool. In fact, you may have started your latest projection with some Yeoman generator!

This leads to the question: practice y'all sympathise the whole process of what your infrastructure really does? Do you need what yous have, specially if yous just spent hours trying to fix your connect webserver livereload functionality?

Have a second to appraise what you lot need. All those tools are only here to aid you, at that place is no other advantage for using them. The more experienced developers I talk to tend to simplify things.

Mutual Mistake #xvi: Non Running The Unit Tests In TDD Mode

Tests volition not make your code free of AngularJS error letters. What they will exercise is assure that your squad doesn't encounter regression bug all the time.

I am writing specifically about unit tests here, not because I feel they are more important than e2e tests, but considering they execute much faster. I must acknowledge that the process I am near to depict is a very pleasurable ane.

Test Driven Evolution as an implementation for east.thousand. gulp-karma runner, basically runs all your unit tests on every file salvage. My favorite way to write tests is, I only write empty assurances first:

          describe('some module', part () {   it('should call the name-information technology service…', office () {     // leave this empty for now   });   ... });                  

Subsequently that, I write or refactor the actual code, then I come up back to the tests and fill in the assurances with actual examination code.

Having a TDD task running in a terminal speeds upwardly the process past about 100%. Unit of measurement tests execute in a matter of a few seconds, fifty-fifty if you lot have a lot of them. Just save the exam file and the runner will selection it upwardly, evaluate your tests, and provide feedback instantly.

With e2e tests, the process is much slower. My advice - split e2e tests up into test suites and only run 1 at a time. Protractor has back up for them, and beneath is the lawmaking I use for my test tasks (I like gulp).

          'use strict';  var gulp = require('gulp'); var args = require('yargs').argv; var browserSync = require('browser-sync'); var karma = require('gulp-karma'); var protractor = require('gulp-protractor').protractor; var webdriverUpdate = require('gulp-protractor').webdriver_update;  function examination() {   // Be certain to return the stream   // Notation: Using the fake './foobar' then equally to run the files   // listed in karma.conf.js INSTEAD of what was passed to   // gulp.src !   return gulp.src('./foobar')     .piping(karma({       configFile: 'test/karma.conf.js',       activeness: 'run'     }))     .on('error', office(err) {       // Make sure failed tests cause gulp to go out non-zero       // console.log(err);       this.emit('stop'); //instead of erroring the stream, end information technology     }); }  function tdd() {   return gulp.src('./foobar')     .pipe(karma({       configFile: 'examination/karma.conf.js',       activeness: 'start'     }))     .on('error', office(err) {       // Make sure failed tests cause gulp to exit non-nil       // console.log(err);       // this.emit('end'); // not ending the stream hither     }); }  office runProtractor () {    var statement = args.suite || 'all';      // Notation: Using the simulated './foobar' so as to run the files   // listed in protractor.conf.js, instead of what was passed to   // gulp.src   return gulp.src('./foobar')     .pipe(protractor({       configFile: 'examination/protractor.conf.js',       args: ['--suite', argument]     }))     .on('error', role (err) {       // Make sure failed tests cause gulp to exit not-zero       throw err;     })     .on('finish', function () {       // Close browser sync server       browserSync.exit();     }); }  gulp.job('tdd', tdd); gulp.job('exam', examination); gulp.task('test-e2e', ['webdriver-update'], runProtractor); gulp.task('webdriver-update', webdriverUpdate);                  

A - chrome breakpoints

Chrome dev tools permit you to indicate at a specific place in whatever of the files loaded into the browser, pause code execution at that point, and let you lot interact with all the variables available from that bespeak. That is a lot! That functionality does not require you to add any code at all, everything happens in the dev tools.

Not only you lot get access to all the variables, you also see the call stack, print stack traces, and more. You can fifty-fifty configure it to work with minified files. Read about it hither.

There are other ways you lot can become similar run-time access, e.g. by adding console.log() calls. Merely breakpoints are more sophisticated.

AngularJS too allows you to access scope through DOM elements (as long as debugInfo is enabled), and inject available services through the console. Consider the following in the console:

          $(document.trunk).telescopic().$root                  

or signal at an element in the inspector, and then:

          $($0).scope()                  

Even if debugInfo is not enabled, y'all tin can practise:

          athwart.reloadWithDebugInfo()                  

And have it bachelor subsequently reload:

To inject and interact with a service from the console, try:

          var injector = $(certificate.trunk).injector(); var someService = injector.become('someService');                  

B - chrome timeline

Another great tool that comes with dev tools is the timeline. That volition allow you to record and analyse your app'southward live performance every bit you are using it. The output shows, amid others, memory usage, frame rate, and the autopsy of the unlike processes that occupy the CPU: loading, scripting, rendering, and painting.

If you lot feel that your app'south functioning degrades, you volition near likely exist able to discover the crusade for that through the timeline tab. Just record your deportment which led to performance issues and see what happens. Too many watchers? You volition see yellowish bars taking a lot of space. Memory leaks? Y'all can see how much memory was consumed over fourth dimension on a graph.

A detailed description: https://developer.chrome.com/devtools/docs/timeline

C - inspecting apps remotely on iOS and Android

If y'all are developing a hybrid app or a responsive web app, you lot tin access your device'southward panel, DOM tree, and all other tools available either through Chrome or Safari dev tools. That includes the WebView and UIWebView.

First, offset your spider web server on host 0.0.0.0 so that it is accessible from your local network. Enable web inspector in settings. So connect your device to your desktop and access your local development folio, using your machine's ip instead of the regular "localhost". That is all information technology takes, your device should now be available to you from your desktop's browser.

Here are the detailed instructions for Android And for iOS, unofficial guides are to be constitute easily through google.

I recently had some cool experience with browserSync. It works in a like manner to livereload, only it as well actually syncs all browsers that are viewing the same page through browserSync. That includes user interaction such equally scrolling, clicking on buttons, etc. I was looking at the iOS app'south log output while controlling the folio on the iPad from my desktop. It worked nicely!

Common Mistake #18: Not Reading The Source Code On The NG-INIT Example

Ng-init, from the sound of information technology, should exist similar to ng-if and ng-repeat, correct? Did you always wonder why there is a comment in the docs that information technology should non exist used? IMHO that was surprising! I would expect the directive to initialize a model. That's likewise what it does, but… it is implemented in a different way, that is, it does not scout the attribute value. You don't need to browse through AngularJS source code - let me bring it to you:

          var ngInitDirective = ngDirective({   priority: 450,   compile: part() {     return {       pre: role(telescopic, element, attrs) {         telescopic.$eval(attrs.ngInit);       }     };   } });                  

Less than you would expect? Quite readable, as well the bad-mannered directive syntax, isn't it? The sixth line is what it is all virtually.

Compare it to ng-show:

          var ngShowDirective = ['$animate', part($breathing) {   return {     restrict: 'A',     multiElement: true,     link: office(scope, chemical element, attr) {       scope.$watch(attr.ngShow, function ngShowWatchAction(value) {         // we're calculation a temporary, blitheness-specific class for ng-hibernate since this way         // we can control when the element is really displayed on screen without having         // to have a global/greedy CSS selector that breaks when other animations are run.         // Read: https://github.com/angular/athwart.js/problems/9103#issuecomment-58335845         $animate[value ? 'removeClass' : 'addClass'](element, NG_HIDE_CLASS, {           tempClasses: NG_HIDE_IN_PROGRESS_CLASS         });       });     }   }; }];                  

Again, the sixth line. In that location is a $lookout man in that location, that's what makes this directive dynamic. In the AngularJS source code, a big role of all the lawmaking are comments that describe code that was more often than not readable from the beginning. I believe it is a corking fashion to acquire most AngularJS.

Conclusion

This guide covering most common AngularJS mistakes is almost twice every bit long as the other guides. It turned out that fashion naturally. The need for high quality JavaScript front cease engineers is very high. AngularJS is then hot right now, and it has been belongings a stable position among the most popular development tools for a few years. With AngularJS 2.0 on the way, it will probably boss for years to come.

What is great about front-end development is that it is very rewarding. Our work is visible instantly, and people interact directly with the products nosotros deliver. The fourth dimension spent learning JavaScript, and I believe we should focus on the JavaScript language, is a very adept investment. It is the linguistic communication of the Internet. The competition is super strong! There is ane focus for the states - user feel. To be successful, we need to cover everything.

Source code used in these examples can exist downloaded from GitHub. Experience free to download it and make it your own.

I wanted to give credits to four publishing developers that inspired me the nigh:

  • Ben Nadel
  • Todd Motto
  • Pascal Precht
  • Sandeep Panda

I also wanted to thank all the great people on FreeNode #angularjs and #javascript channels for many excellent conversations, and continuous back up.

And finally, always remember:

          // when in doubt, comment it out! :)                  

perkinswhered.blogspot.com

Source: https://www.toptal.com/angular-js/top-18-most-common-angularjs-developer-mistakes

0 Response to "How to Make Which Repeating Data Again Get Repeted Values in Angularjs"

Mag-post ng isang Komento

Iklan Atas Artikel

Iklan Tengah Artikel 1

Iklan Tengah Artikel 2

Iklan Bawah Artikel