Skip to content
This repository was archived by the owner on Apr 12, 2024. It is now read-only.
This repository was archived by the owner on Apr 12, 2024. It is now read-only.

Binding / Expression Namespaces (better BindOnce alternative) #6354

Closed
@ProLoser

Description

@ProLoser

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:

Expression Namespaces

Examples:

  • ng-bind="{ personNamespace: person.name }"
  • {{personNamespace:: person.age}}
  • ng-if="personNamespace:: person.alive"
  • ng-repeat="personNamespace:: child in person.children "
  • $scope.$watch('personNamespace:: person.height', ... )
  • {{i18n:: i18n['welcome.message']}}
  • ng-if="login:: hasPermission('DeleteUsers')"

These would all be handled by:

ng-namespace="{ personNamespace: person }" or $scope.$namespace({ personNamespace: 'person' })

Only the ng-namespace expression is evaluated on every $digest. When the expression changes in value, all namespaced bindings get re-evaluated.

The person value would be watched normally, and every time it changes, the personNamespace bindings throughout the rest of the application would be refreshed.

This 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.

Benefits:

  • You can intermix multiple namespaces together, unlike bindonce which sections off groups of bindings
  • Completely backwards compatible with the old syntax
  • Simplistic syntax that can be used anywhere expressions are used
  • All bindings are bind-occasionally
  • Problems such as internationalization, permission restrictions, etc can all be tackled with traditional bindings without needing to create workaround directives
  • Additional edge-cases for undeclared namespaces (if the namespace isn't declared in ng-namespace)
    • If namespace is undeclared, behave like bind-once?
      {{once:: person.name}}
    • If namespace is undeclared, fall back to normal watching behavior?
      {{always:: person.selected}}

Issues:

  • Using ng-namespace (a directive) may be confusing alongside namespaces in watchers (controllers). I am not 100% sure the watcher version is necessary however.

Implementation

I 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.

This separates the expression being WATCHED from the expression being ECHO'd

It'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.

TL;DR:

Using 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.

<div ng-namespace="person:: person.id">
  <h1>{{person:: person.name}} ({{person:: person.age}})</h1>
  <h2>{{person:: person.title}}</h2>
  <p>Gender: {{person:: person.gender}}, Company: {{person:: person.company}}</p>
</div>

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions