Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Instantiate only one directive playing a particular role #3011

Closed
vsavkin opened this issue Jul 13, 2015 · 10 comments
Closed

Instantiate only one directive playing a particular role #3011

vsavkin opened this issue Jul 13, 2015 · 10 comments
Assignees
Labels
area: core Issues related to the framework runtime core: directive matching effort2: days feature: under consideration Feature request for which voting has completed and the request is now under consideration feature Issue that requests a new feature
Milestone

Comments

@vsavkin
Copy link
Contributor

vsavkin commented Jul 13, 2015

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

@mhevery @tbosch @jeffbcross

@mhevery
Copy link
Contributor

mhevery commented Oct 25, 2015

I think we should go with Proposal 1 of using roles The rules would be simple.

  • Only one directive from each role can be present per element.
  • If more then one directive with a given role matches on an element, chose the one with highest selector specificity.

NOTE: We could optionally have a concept of priority, but with have bad examples from AngularJS v1 where we did have priority and it was difficult to come up with absolute scale for priorities across libraries.

@awerlang
Copy link
Contributor

awerlang commented Mar 1, 2016

I like the first proposal, but I think we can make it more inclusive. What about:

import {DefaultValueAccessor} from 'angular2/common';

@Directive({
  selector: "input[type=checkbox][ng-control]",
  override: DefaultValueAccessor
})
class CheckeboxValueAccessor extends DefaultValueAccessor {}

Rules:

  • Build an hierarchy from the directives that matches the element, based on the override field.
  • If there are two or more overrides, disallow and throw?
  • Do not attach to the element all directives that have been overriden

@Delagen
Copy link
Contributor

Delagen commented Jun 22, 2016

any movement in solving this issue?

@mhevery mhevery added area: core Issues related to the framework runtime and removed comp: core/view/compiler labels Sep 7, 2016
@JohannesHoppe
Copy link
Contributor

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

@ashish173
Copy link

I was reading the code that is where I came across this issue/suggestion, just curious what are the plans for this feature @vsavkin @mhevery @IgorMinar @vicb

@JohannesHoppe
Copy link
Contributor

FYI, for my particular problem I was able to find a workaround:
https://github.com/JohannesHoppe/angular-date-value-accessor

@splincode
Copy link
Contributor

@vsavkin Is the issue relevant?

@CSchulz
Copy link

CSchulz commented Apr 5, 2019

For our team this issue is relevant, because we have a common value accessor in the commons module and some specific one in the application module.

We want to overwrite the common value accessor with a more specific selector without having the requirement to exclude all specific value accessors in the common module.

@angular-robot angular-robot bot added the feature: under consideration Feature request for which voting has completed and the request is now under consideration label May 21, 2021
@alxhub
Copy link
Member

alxhub commented Dec 15, 2023

I'm going to close this issue, as we believe this problem is well suited to being solved in userspace. It's a separate question whether @angular/forms should support some kind of priority system across value accessors.

@alxhub alxhub closed this as not planned Won't fix, can't repro, duplicate, stale Dec 15, 2023
Feature Requests automation moved this from Close with Followup to Closed Dec 15, 2023
@angular-automatic-lock-bot
Copy link

This issue has been automatically locked due to inactivity.
Please file a new issue if you are encountering a similar or related problem.

Read more about our automatic conversation locking policy.

This action has been performed automatically by a bot.

@angular-automatic-lock-bot angular-automatic-lock-bot bot locked and limited conversation to collaborators Jan 15, 2024
Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
area: core Issues related to the framework runtime core: directive matching effort2: days feature: under consideration Feature request for which voting has completed and the request is now under consideration feature Issue that requests a new feature
Projects
No open projects
Development

No branches or pull requests