└── README.md /README.md: -------------------------------------------------------------------------------- 1 | ## Tips & Tricks 2 | 3 | #### 1. Running a code when you aren't sure whether it will be called from within angular context or outside it. 4 | 5 | ```javascript 6 | $scope.evalAsync(function () { 7 | // Your code here. 8 | }); 9 | ``` 10 | 11 | Note: In case you are sure you are out of angular context, its better to call `$scope.$digest` after your code instead of using `$scope.$apply` because `$apply` will call `$digest` on `$rootScope` which is much heavier. 12 | 13 | #### 2. Check if a form is dirty or invalid from your controller. 14 | 15 | ```javascript 16 | // `formName` is value of name attribute of the form. 17 | // If form is dirty. 18 | if ($scope.formName.$dirty) { 19 | } 20 | 21 | // If form is invalid. 22 | if ($scope.formName.$invalid) { 23 | } 24 | ``` 25 | 26 | Note: The name attribute value of the form cannot be hyphenated as that becomes a JS variable. 27 | 28 | #### 3. Watching for changes in `name` of any user in a list of users: 29 | 30 | ```javascript 31 | $scope.watchCollection( 32 | function watchFn() { 33 | return $scope.users.map(function (user) { 34 | return user.name; 35 | }); 36 | }), 37 | function watchListener() { 38 | // Fired when name of any user changes. 39 | } 40 | }); 41 | ``` 42 | 43 | 44 | #### 4. Make a particular HTML section compile only after some asynchronous data is fetched: 45 | 46 | In Controller: 47 | ```javascript 48 | $http.get('data_endpoint').then(function () { 49 | $scope.isDataFetched = true; 50 | }) 51 | ``` 52 | 53 | In HTML: 54 | ```html 55 |
56 | 57 |
58 | ``` 59 | 60 | 61 | #### 5. Angular `copy` function copies the prototype properties of an object on the new object. BEWARE: If you watch such an object, you will probably get stuck in an infinite loop because `$digest` will always find the old and new objects different due to the abnormal behavior of `angular.copy`. 62 | 63 | ```javascript 64 | var obj = {a: 1}; 65 | var obj1 = Object.create(obj); 66 | 67 | obj1.hasOwnProperty('a'); // Returns false 68 | 69 | var newCopy = angular.copy(obj1); 70 | newCopy.hasOwnProperty('a'); // Returns true. Property `a` is own the object itself now. 71 | 72 | ``` 73 | 74 | 75 | ## Performance: 76 | 77 | #### 1. Use track by in ng-repeat expression to avoid re-rendering of compelete list: 78 | 79 | ```html 80 | 81 |
  • 82 | 83 | 84 |
  • 85 | 86 | ``` 87 | 88 | #### 2. Debounce the change in model to prevent watchers from firing too frequently (Angular 1.3): 89 | 90 | ```html 91 |
    94 | ``` 95 | This will change model value only after staying idle for 300ms after the last change happened in input value. 96 | 97 | 98 | #### 3. If your page has too many watchers being used to display content which doesn't change with time, use [bindonce](https://github.com/Pasvaz/bindonce) 99 | . 100 | 101 | Adds one watcher for `user.name`: 102 | 103 | ``` 104 | Welcome to the app, {{user.name}} 105 | ``` 106 | 107 | Using bindonce, no watcher remains once `user.name` is available: 108 | 109 | ```html 110 | Welcome to the app, 111 | ``` 112 | 113 | Note: Angular 1.3 has a similar feature: 114 | 115 | #### 4. If you have a directive that is inside an ng-repeat, its `compile` function is called only once throughout the ng-repeat. So place your common code for directives in compile function so that it executes only once per ng-repeat loop. 116 | 117 | 118 | #### 5. Watching for an item change in a list: 119 | 120 | Bad - Watch with deep comparison creates copies of objects: 121 | ```javascript 122 | $scope.watch('yourList', 123 | function watchListener() { 124 | // Fired when name of any user changes. 125 | } 126 | }, true); 127 | ``` 128 | 129 | Good: 130 | ```javascript 131 | $scope.watchCollection('yourList', 132 | function watchListener() { 133 | // Fired when name of any user changes. 134 | } 135 | }); 136 | ``` 137 | 138 | #### 6. Avoid using filters on large arrays. Filters run on each digest loop and creates new array everytime it runs. In such cases its better to manually watch your list and do filtering when a change is detected. 139 | 140 | Bad - Filter runs on each digest loop. 141 | 142 | ```html 143 |
  • 144 | ``` 145 | 146 | Good: 147 | 148 | In Controller: 149 | ```javascript 150 | $scope.filteredItems = $scope.items; 151 | $scope.$watchCollection('items', function () { 152 | // Apply filter on change detection 153 | $scope.filteredItems = myComplexFilter($scope.items); 154 | }); 155 | ``` 156 | 157 | In HTML: 158 | ```html 159 |
  • 160 | ``` 161 | 162 | ## Debugging: 163 | 164 | #### 1. Many a times you want to know when an object's particular property gets set. Here is a neat trick to do it: 165 | 166 | ```javascript 167 | var obj = {a: 2}; 168 | 169 | var _a = obj.a; 170 | 171 | Object.defineProperty(a, 'a', { 172 | get: function () { return _a; }, 173 | set: function (val) { _a = val; console.log('prop changed'); } 174 | }); 175 | 176 | // You'll get a console log whenever the property changes. 177 | ``` 178 | 179 | ### Contributing 180 | - - - 181 | 182 | If you have some Angular tips and tricks you would like to get added here, please open pull request for the same. 183 | 184 | 185 | ### Credits 186 | - - - 187 | 188 | The awesome front-end folks at ![Wingify](http://wingify.com/images/logo_wingify_big.png) 189 | --------------------------------------------------------------------------------