Instantiate only one directive playing a particular role
See original GitHub issueWe need to provide a way to tell the compiler not to instantiate a directive when there is another, more specialized, directive that does the same job.
Imagine we have a default value accessor directive used by forms.
@Directive({
selector: '[ng-control]'
})
class DefaultValueAccessor {}
Now, let’s add a more specialized value accessor that can handle checkboxes.
@Directive({
selector: "input[type=checkbox][ng-control]
})
class CheckeboxValueAccessor {}
In the following template I would like the first input to use DefaultValueAccessor, and the second input to use CheckeboxValueAccessor.
<input type="text" ng-control="name">
<input type="checkbox" ng-control="isAmerican">
Unfortunately, the second input will end up having two value accessors. So this approach does not work.
What we have to do right now is to write mutually exclusive selectors that look like this:
@Directive({
selector: 'input:not([type=checkbox])[ng-control],textarea[ng-control]'
})
class DefaultValueAccessor {}
Even though this approach is not elegant, it sort of works when one person/team provides a set of directives. If, however, I would like to add a third-party value accessor, I will end up having the same problem: I will have two value accessors created for the same element.
Proposal 1
Have a mechanism to tell the compiler that all value accessors play the same role. So the compiler can instantiate only one for each element. The compiler can take the last directives from the list of directives that matches a element.
@Directive({selector: '[ng-control]', role: 'valueAccessor')
class DefaultValueAccessor{}
@Directive({selector: 'some custom stuff', role: 'valueAccessor')
class CustomValueAccessor{}
const directives = [DefaultValueAccessor, CustomValueAccessor];
If CustomValueAccessor matches the element, DefaultValueAccessor will not be instantiated.
We can also try to unify this concept with exportAs
, because the role and the local name should always match.
Proposal 2
Have a generic mechanism for a directive to specify a compile-time predicate to determine if it should be instantiated.
function lastValueAccessor(thisBinding, bindings) {
// find thisBinding in bindings, and make sure that this is the last value accessor.
}
@Directive({selector: '[ng-control]', predicate:lastValueAccessor)
class DefaultValueAccessor{}
@Directive({selector: 'some custom stuff', predicate:lastValueAccessor)
class CustomValueAccessor{}
This can be useful for other scenarios. For example, if you want to make sure that the dom structure matches some required shape. This may not work with Dart transformers.
Issue Analytics
- State:
- Created 8 years ago
- Reactions:25
- Comments:8 (6 by maintainers)
Any plans for Angular 2.1? Plain HTML5 forms are just painfull (e.g.
<input type="date">
) Right now we are more or less forced to use some third-party libraries to fill the gap…I like the first proposal, but I think we can make it more inclusive. What about:
Rules: