{"id":19541396,"url":"https://github.com/wingify/angularjs-tips","last_synced_at":"2025-02-26T05:18:27.652Z","repository":{"id":21397175,"uuid":"24715052","full_name":"wingify/angularjs-tips","owner":"wingify","description":"Tips and tricks for doing things in AngularJS framework.","archived":false,"fork":false,"pushed_at":"2015-07-15T12:29:43.000Z","size":195,"stargazers_count":48,"open_issues_count":1,"forks_count":7,"subscribers_count":47,"default_branch":"master","last_synced_at":"2025-01-08T18:45:18.463Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":null,"has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/wingify.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-10-02T10:31:09.000Z","updated_at":"2022-12-10T17:23:03.000Z","dependencies_parsed_at":"2022-07-30T04:47:59.441Z","dependency_job_id":null,"html_url":"https://github.com/wingify/angularjs-tips","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wingify%2Fangularjs-tips","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wingify%2Fangularjs-tips/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wingify%2Fangularjs-tips/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/wingify%2Fangularjs-tips/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/wingify","download_url":"https://codeload.github.com/wingify/angularjs-tips/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240795151,"owners_count":19858754,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2024-11-11T03:10:15.137Z","updated_at":"2025-02-26T05:18:27.451Z","avatar_url":"https://github.com/wingify.png","language":null,"funding_links":[],"categories":[],"sub_categories":[],"readme":"## Tips \u0026 Tricks\n\n#### 1. Running a code when you aren't sure whether it will be called from within angular context or outside it.\n\n```javascript\n$scope.evalAsync(function () {\n    // Your code here.\n});\n```\n\nNote: 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.\n\n#### 2. Check if a form is dirty or invalid from your controller.\n\n```javascript\n// `formName` is value of name attribute of the form.\n// If form is dirty.\nif ($scope.formName.$dirty) {\n}\n\n// If form is invalid.\nif ($scope.formName.$invalid) {\n}\n```\n\nNote: The name attribute value of the form cannot be hyphenated as that becomes a JS variable.\n\n#### 3. Watching for changes in `name` of any user in a list of users:\n\n```javascript\n$scope.watchCollection(\n\tfunction watchFn() {\n\t\treturn $scope.users.map(function (user) {\n\t\t\treturn user.name;\n\t\t});\n\t}),\n\tfunction watchListener() {\n\t\t// Fired when name of any user changes.\n\t}\n});\n```\n\n\n#### 4. Make a particular HTML section compile only after some asynchronous data is fetched:\n\nIn Controller:\n```javascript\n$http.get('data_endpoint').then(function () {\n\t$scope.isDataFetched = true;\n})\n```\n\nIn HTML:\n```html\n\u003cdiv ng-if=\"isDataFetched\"\u003e\n\t\u003c!-- Some complex HTML that needs fetched data --\u003e\n\u003c/div\u003e\n```\n\n\n#### 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`.\n\n```javascript\nvar obj = {a: 1};\nvar obj1 = Object.create(obj);\n\nobj1.hasOwnProperty('a'); // Returns false\n\nvar newCopy = angular.copy(obj1);\nnewCopy.hasOwnProperty('a'); // Returns true. Property `a` is own the object itself now.\n\n```\n\n\n## Performance:\n\n#### 1. Use track by in ng-repeat expression to avoid re-rendering of compelete list:\n\n```html\n\u003c!-- Normal --\u003e\n\u003cli ng-repeat=\"item in items\"\u003e\u003c/li\u003e\n\n\u003c!-- Better --\u003e\n\u003cli ng-repeat=\"item in items track by item.id\"\u003e\u003c/li\u003e\n\n```\n\n#### 2. Debounce the change in model to prevent watchers from firing too frequently (Angular 1.3):\n\n```html\n\u003cinput type=\"text\" name=\"userName\"\n       ng-model=\"user.name\"\n       ng-model-options=\"{ debounce: 300 }\" /\u003e\u003cbr /\u003e\n```\nThis will change model value only after staying idle for 300ms after the last change happened in input value.\n\n\n#### 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)\n.\n\nAdds one watcher for `user.name`:\n\n```\nWelcome to the app, {{user.name}}\n```\n\nUsing bindonce, no watcher remains once `user.name` is available:\n\n```html\nWelcome to the app, \u003cspan bo-text=\"user.name\"\u003e\u003c/span\u003e\n```\n\nNote: Angular 1.3 has a similar feature:\n\n#### 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.\n\n\n#### 5. Watching for an item change in a list:\n\nBad - Watch with deep comparison creates copies of objects:\n```javascript\n$scope.watch('yourList',\n\tfunction watchListener() {\n\t\t// Fired when name of any user changes.\n\t}\n}, true);\n```\n\nGood:\n```javascript\n$scope.watchCollection('yourList',\n\tfunction watchListener() {\n\t\t// Fired when name of any user changes.\n\t}\n});\n```\n\n#### 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.\n\nBad - Filter runs on each digest loop.\n\n```html\n\u003cli ng-repeat=\"item in items | myComplexSortFilter\"\u003e\u003c/li\u003e\n```\n\nGood:\n\nIn Controller:\n```javascript\n$scope.filteredItems = $scope.items;\n$scope.$watchCollection('items', function () {\n    // Apply filter on change detection\n    $scope.filteredItems = myComplexFilter($scope.items);\n});\n```\n\nIn HTML:\n```html\n\u003cli ng-repeat=\"item in newitemsList\"\u003e\u003c/li\u003e\n```\n\n## Debugging:\n\n#### 1. Many a times you want to know when an object's particular property gets set. Here is a neat trick to do it:\n\n```javascript\nvar obj = {a: 2};\n\nvar _a = obj.a;\n\nObject.defineProperty(a, 'a', {\n get: function () { return _a; },\n set: function (val) { _a = val; console.log('prop changed'); }\n});\n\n// You'll get a console log whenever the property changes.\n```\n\n### Contributing\n- - -\n\nIf you have some Angular tips and tricks you would like to get added here, please open pull request for the same.\n\n\n### Credits\n- - -\n\nThe awesome front-end folks at ![Wingify](http://wingify.com/images/logo_wingify_big.png)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwingify%2Fangularjs-tips","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fwingify%2Fangularjs-tips","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fwingify%2Fangularjs-tips/lists"}