Versions Compared

Key

  • This line was added.
  • This line was removed.
  • Formatting was changed.

...

Warning

Please dont use angular batarang (stable) plugin when checking for the watchers. This plugin is not the official one of Batarang. It gives the false count.

 


  1. One-time binding ( :: ) 

    Angular brings in support for one way binding from 1.3 but there are more things. One-time binding can be used in cases where the expression will not change once the value is set.
    For example:

    Code Block
    languagexml
    titleone-time binding
     <span>{{::patient.identifier}}</span>

    Since patient's identifier wont change once set, it is a good candidate for one-time binding. Angular doc says,
    "One-time expressions will stop recalculating once they are stable, which happens after the first digest if the expression result is a non-undefined value ". There is a catch here. Watchers will stay alive till the expression is 'undefined'. As long as patient.identifier is undefined, watcher will be alive.

    Another example:

    Code Block
    <span ng-if="::observation.isRequired()" class="asterick">*</span>


    Code Block
    titleobservation.js
       isRequired: function () {
            return this.conceptUIConfig.required;
       },

    In this example, if 'required' property is not present in conceptUIConifg, it will always return undefined and watcher will be alive always. Instead the condition can be changed to  'this.conceptUIConfig.required == true' .

    Also we should pass attributes to directive as one-time binding wherever necessary.
    Example: 

    Code Block
    titlePassing attributes to directive as one-time binding
    <section address-fields data-address-levels="::addressLevels" data-address="patient.address"
             field-validation="::fieldValidation"></section>

    'address-levels' and 'field-validation' are read only attributes for 'address-fields' directive. i.e. It does not update anything in addressLevels and fieldValidation, so it can be added as one-time binding attributes.

    Example: Here is a real-world example of a commit to improve performance in a display control by switching to one-time binding.


  2. Directive's optional attributes

    Angular directive can have attributes declared as optional using '=?'.
    Lets say, we have a directive called 'attribute-types' with isolated scope

    Code Block
    languagejs
    titleattributeTypes.js
     scope : {
        targetModel : '=',
        attribute : '=',
        fieldValidation : '=',
        isAutoComplete: '&',
        getAutoCompleteList: '&',
        getDataResults: '&',
        isReadOnly: '&',
        isForm : '='
    }

    And it is used in two different places as follows:

    Code Block
    languagexml
    titleUsage 1
    <attribute-types target-model="patientProgram.patientProgramAttributes" attribute="attributeType"></attribute-types>


    Code Block
    languagexml
    titleUsage 2
    <attribute-types target-model="patient" attribute="::attribute" field-validation="::fieldValidation"
                     is-auto-complete="isAutoComplete" get-auto-complete-list="getAutoCompleteList"
                     get-data-results="getDataResults" is-read-only="isReadOnly"></attribute-types>

    Usage 1 passes only two attributes and usage 2 passes more than two. So with the usage 1, attributes other than 'targetModel' and 'attribute' will be undefined. So watchers will be alive for the other attributes 'fieldValidation' and 'isForm'. To avoid this, those attributes can be marked as optional using '=?' instead of '='. When we do that, watcher will be added if attribute is passed and if it is not passed, no watcher will be added to the attribute.

  3.  Use track by with ng-repeat.

    http://www.codelord.net/2014/04/15/improving-ng-repeat-performance-with-track-by/

  4. Disable DebugInfo in production

    Angular by default adds some classes like ng-bindingng-scope, ng-isolate-scope to the DOM elements using jquery data property all the way through DOM hierarchy which takes some significant time while loading. 

    We can disable it in production using 

    Code Block
    languagejs
    titleapp.js
      $compileProvider.debugInfoEnabled(false);

    More info on: https://docs.angularjs.org/guide/production

    This gave us a significant performance boost.
     

  5. Use css class to show and hide small elements instead of ng-if/ng-show

    For example: 

    The arrow that we show in the image is used to indicate whether the section has been expanded or collapsed.
    Instead of hiding and showing it using ng-show like below:

    Code Block
    <div toggle="displayPatientContactDetails">
        <i class="fa fa-caret-right" ng-hide="displayPatientContactDetails"></i>
        <i class="fa fa-caret-down" ng-show="displayPatientContactDetails"></i>  
        <span>Patient Contact Details</span> 
     </div>

    The 'toggle' directive toggles the value of  'displayPatientContactDetails' and adds a class called 'active' to the div based on whether displayPatientContactDetails is true or not . The arrow can be shown or hidden using css of 'active' class.

    Code Block
    languagecss
    div{
      &.active{
        .fa-caret-right{
          display: none;
        }
        .fa-caret-down{
          display: block;
        }
      }
      .fa-caret-down{
        display:none;
      }
    }

    So the html can be changed to:

    Code Block
    languagexml
    <div toggle="displayPatientContactDetails">
        <i class="fa fa-caret-right"></i>
        <i class="fa fa-caret-down"></i>  
        <span>Patient Contact Details</span> 
     </div>


    This is one such example. The same approach can be used for multiple small elements which does not have any data binding or handlers.

 

...