{"action":"created","issue":{"url":"https://api.github.com/repos/angular/angular.js/issues/6354","labels_url":"https://api.github.com/repos/angular/angular.js/issues/6354/labels{/name}","comments_url":"https://api.github.com/repos/angular/angular.js/issues/6354/comments","events_url":"https://api.github.com/repos/angular/angular.js/issues/6354/events","html_url":"https://github.com/angular/angular.js/issues/6354","id":27906701,"number":6354,"title":"Binding / Expression Namespaces (better BindOnce alternative)","user":{"login":"ProLoser","id":67395,"avatar_url":"https://avatars.githubusercontent.com/u/67395?v=3","gravatar_id":"","url":"https://api.github.com/users/ProLoser","html_url":"https://github.com/ProLoser","followers_url":"https://api.github.com/users/ProLoser/followers","following_url":"https://api.github.com/users/ProLoser/following{/other_user}","gists_url":"https://api.github.com/users/ProLoser/gists{/gist_id}","starred_url":"https://api.github.com/users/ProLoser/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/ProLoser/subscriptions","organizations_url":"https://api.github.com/users/ProLoser/orgs","repos_url":"https://api.github.com/users/ProLoser/repos","events_url":"https://api.github.com/users/ProLoser/events{/privacy}","received_events_url":"https://api.github.com/users/ProLoser/received_events","type":"User","site_admin":false},"labels":[{"url":"https://api.github.com/repos/angular/angular.js/labels/component:%20misc%20core","name":"component: misc core","color":"fef2c0"},{"url":"https://api.github.com/repos/angular/angular.js/labels/frequency:%20high","name":"frequency: high","color":"f7c6c7"},{"url":"https://api.github.com/repos/angular/angular.js/labels/type:%20feature","name":"type: feature","color":"00a606"}],"state":"open","locked":false,"assignee":null,"milestone":{"url":"https://api.github.com/repos/angular/angular.js/milestones/27","labels_url":"https://api.github.com/repos/angular/angular.js/milestones/27/labels","id":489171,"number":27,"title":"Backlog","description":"Holds the backlog of issues and pull requests that have been triaged.\r\n\r\nBefore assigning items to this milestone they should be labelled, at the very least with the correct \"type\" label (i.e. \"issue\", \"pr\", \"bug\", \"regression\", \"chore\", \"docs\", etc).  Preferably you should also check for duplicate issues/PRs, note CLA status and assign \"complexity\" and \"impact\" labels too.","creator":{"login":"IgorMinar","id":216296,"avatar_url":"https://avatars.githubusercontent.com/u/216296?v=3","gravatar_id":"","url":"https://api.github.com/users/IgorMinar","html_url":"https://github.com/IgorMinar","followers_url":"https://api.github.com/users/IgorMinar/followers","following_url":"https://api.github.com/users/IgorMinar/following{/other_user}","gists_url":"https://api.github.com/users/IgorMinar/gists{/gist_id}","starred_url":"https://api.github.com/users/IgorMinar/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/IgorMinar/subscriptions","organizations_url":"https://api.github.com/users/IgorMinar/orgs","repos_url":"https://api.github.com/users/IgorMinar/repos","events_url":"https://api.github.com/users/IgorMinar/events{/privacy}","received_events_url":"https://api.github.com/users/IgorMinar/received_events","type":"User","site_admin":false},"open_issues":721,"closed_issues":740,"state":"open","created_at":"2013-11-18T23:30:35Z","updated_at":"2015-02-01T16:32:44Z","due_on":null,"closed_at":null},"comments":18,"created_at":"2014-02-19T20:28:45Z","updated_at":"2015-02-02T08:48:13Z","closed_at":null,"body":"So lots of people are asking for 'BindOnce' but I actually don't believe this is the best approach to handle performance. Not only does it require specific directives, it also doesn't properly tackle the 'bind-occasionally' scenario, or when it does, it requires a completely different directive. Instead I propose:\r\n\r\n# Expression Namespaces\r\n\r\n**Examples:**\r\n* `ng-bind=\" personNamespace: person.name\"`\r\n* `{{personNamespace: person.age}}`\r\n* `ng-if=\" personNamespace: person.alive \"`\r\n* `ng-repeat=\" personNamespace: child in person.children \"`\r\n* `$scope.$watch(' personNamespace: person.height ', ... )`\r\n* `{{ i18n: i18n['welcome.message'] }}`\r\n* `ng-if=\" login: hasPermission('DeleteUsers') \"`\r\n\r\n**These would all be handled by:**\r\n\r\n`ng-namespace=\" personNamespace: person \"` or `$scope.$namespace('personName', 'person')`\r\n\r\n_Only the `ng-namespace` expression is evaluated on every $digest_. When the expression changes in value, all namespaced bindings get re-evaluated. \r\n\r\nThe `person` value would be watched normally, and every time it changes, the `personNamespace` bindings throughout the rest of the application would be refreshed.\r\n\r\nThis is pretty much JUST 'bind-occasionally' since if the 'occasional' occurance is only once, then you are getting the same benefit of a bind-once.\r\n\r\n## Benefits:\r\n\r\n* You can intermix multiple namespaces together, unlike bindonce which sections off groups of bindings\r\n* Completely backwards compatible with the old syntax\r\n* Simplistic syntax that can be used anywhere expressions are used\r\n* All bindings are bind-occasionally\r\n* Problems such as internationalization, permission restrictions, etc can all be tackled with traditional bindings without needing to create workaround directives\r\n* Additional edge-cases for undeclared namespaces (if the namespace isn't declared in ng-namespace)\r\n  * If namespace is undeclared, behave like bind-once?  \r\n    `{{ once: person.name }}`\r\n  * If namespace is undeclared, fall back to normal watching behavior?  \r\n    `{{ always: person.selected }}`\r\n\r\n## Issues:\r\n\r\n* Using `ng-namespace` (a directive) may be confusing alongside namespaces in watchers (controllers). I am not 100% sure the watcher version is necessary however.\r\n\r\n## Implementation\r\n\r\nI was discussing how the best way to write an efficient translation solution and we realized that instead of using watchers, it's better to use `$broadcast()` to signify that a namespace digest has been triggered. I'm not necessarily saying this is how it should be implemented in the core, but this was one idea we came up with.\r\n\r\n**This separates the expression being WATCHED from the expression being ECHO'd**\r\n\r\nIt's like saying \"Although I want to spit out `person.age` I want you to just monitor `person` for changes\". However what is being 'monitored' is defined in your `ng-namespace`. Each binding or expression is no longer being watched. Instead they are waiting for some sort of `$broadcast('namespace-person')` instead, and only 1 watcher is ever actually used.\r\n\r\n# TL;DR:\r\n\r\nUsing expression 'namespaces' we no longer deal with turning off / on bindings. Instead, only 1 expression is 'watched' and all the other bindings are tied to this one expression. **There is no toggling on and off of bindings**."},"comment":{"url":"https://api.github.com/repos/angular/angular.js/issues/comments/72422988","html_url":"https://github.com/angular/angular.js/issues/6354#issuecomment-72422988","issue_url":"https://api.github.com/repos/angular/angular.js/issues/6354","id":72422988,"user":{"login":"lgalfaso","id":391394,"avatar_url":"https://avatars.githubusercontent.com/u/391394?v=3","gravatar_id":"","url":"https://api.github.com/users/lgalfaso","html_url":"https://github.com/lgalfaso","followers_url":"https://api.github.com/users/lgalfaso/followers","following_url":"https://api.github.com/users/lgalfaso/following{/other_user}","gists_url":"https://api.github.com/users/lgalfaso/gists{/gist_id}","starred_url":"https://api.github.com/users/lgalfaso/starred{/owner}{/repo}","subscriptions_url":"https://api.github.com/users/lgalfaso/subscriptions","organizations_url":"https://api.github.com/users/lgalfaso/orgs","repos_url":"https://api.github.com/users/lgalfaso/repos","events_url":"https://api.github.com/users/lgalfaso/events{/privacy}","received_events_url":"https://api.github.com/users/lgalfaso/received_events","type":"User","site_admin":false},"created_at":"2015-02-02T08:48:13Z","updated_at":"2015-02-02T08:48:13Z","body":"@ProLoser there is a proposal in place at https://docs.google.com/document/d/1XIng9nC_8G48AJ9Pbq8gYSWYvS1dnhiFxpugIKAPBhY/edit\r\nThat said, this is not in the radar for 1.4"}}