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

Proposal: Need ability to add directives to host elements in component declaration. #8785

Closed
jamesmfriedman opened this issue May 23, 2016 · 145 comments
Assignees
Labels
area: core Issues related to the framework runtime core: directive matching core: host and host bindings feature: under consideration Feature request for which voting has completed and the request is now under consideration feature Issue that requests a new feature state: has PR

Comments

@jamesmfriedman
Copy link

I've been digging into Angular 2 and have run into a potential road block for extending certain kinds of components.

In the the following example, I have a button component, and a directive that will apply styles based on touch events. There will be many other objects other than just the button that will inherit the exact same touch behavior. I've explored my options, and I'm at a loss:

  • Directly extend a TouchClass. This seems less than ideal since typescript doesn't support multiple class inheritance, and I'd also like to expose the behavior to consumers for use in their own classes.
  • Fake multiple class inheritance through an interface. This seems like a hack and requires me to redeclare a shim api on every class I'm trying to mix into. https://www.stevefenton.co.uk/2014/02/TypeScript-Mixins-Part-One/
  • Create a helper function that does it through a service directly on elementRef.nativeElement in the component constructor. I really don't want to do this since it states in the docs that nativeElement will be null when running in a worker, and that capability is something I'm the most excited about.

Without getting too deep into the guts, I'd presume that the componentMetadata is available during the components compile time, and that the host property could be scanned for additional directives that could be added dynamically and compiled at the same time. This would allow you to do mixins the angular way: using composable directives to extend functionality, and doing it without breaking view projection. Short example below.

Current behavior
Declaring a directive in componentMetadata.host treats it as a regular attribute

Expected/desired behavior
The directive declared in host would be processed at compile time.

/**
 * App
 */
@Component({
    selector: 'app-component',
    template: '<g-btn>TEST</g-btn>',
    directives: [gBtn, gTouch]
})

export class AppComponent {
    constructor() {

    }
}

/**
 * Touch Directive
 * Will be used in lots and lots of components
 */
@Directive({
    selector: '[g-touch]',
    host: { 
        '(touchstart)': '...',
        '(touchend)': '...',
        '(touchmove)': '...',
        '(touchcancel)': '...'
    }
})

export class gTouch {
    constructor() {

    }
}

/**
 * Simple button component
 */
@Component({
    selector: 'g-btn',
    template: '<ng-content></ng-content>',
    host: {
        'role': 'button',
        // WOULD LOVE FOR THIS TO COMPILE THE DIRECTIVE!
        // right now it just adds an attribute called g-touch
        'g-touch': ' ' 
    }
})

export class gBtn {

    constructor() {

    }
}

Some ideas of how this could work:

// Option 1: just scan the host properties for directives.
// This would be my ideal, simple and understandable
@Component({
    selector: 'g-btn',
    template: '<ng-content></ng-content>',
    host: {
        'role': 'button',
        'g-touch': true // or {prop: 'foo'} or string
    }
})

// Option 2: definitely more declarative using a hostDirectives property
// more declarative, albeit more annoying to have to reimport the touch class
@Component({
    selector: 'g-btn',
    template: '<ng-content></ng-content>',
    hostDirectives: gTouch,
    host: {
        'role': 'button',
        'g-touch': true
    }
})

// Option 3: declare host directives as its own thing, still just
// use keys pointing to bool, obj, or string
@Component({
    selector: 'g-btn',
    template: '<ng-content></ng-content>',
    hostDirectives: {
        'g-touch': {someOption: someOption}
    },
    host: {
        'role': 'button',
    }
});

// Option 4: Not a huge fan of this one, but understandable if
// people want to keep one host property
@Component({
    selector: 'g-btn',
    template: '<ng-content></ng-content>',
    host: {
        'role': 'button',
        _directives: {
            'g-touch': true
        }
    }
});

Thanks everyone, Angular 2 is looking great!. Let me know if theres something I'm missing.

@pkozlowski-opensource pkozlowski-opensource added feature Issue that requests a new feature comp: core labels Jun 16, 2016
@Andy1605
Copy link

Andy1605 commented Jul 7, 2016

I am currently developing a large client and am therefore trying to break down all GUI related problems into reusable Angular2 directives. This always leads me to that same problem, as james pointed out perfectly.
This really has to work somehow for the sake of good modular and dynamic architecture. The touch example is only one of many scenarios where this is needed. e.g. Drag&Drop, Resize observing, etc. etc. etc.
Made another example as plunker:
https://plnkr.co/edit/J65THEMic0yhObt1LkCu?p=info

Is there any chance this functionality will be added any time soon?

Here is a StackOverflow question related to this: http://stackoverflow.com/questions/37148080/use-angular2-directive-in-host-of-another-directive

@mhevery mhevery added area: core Issues related to the framework runtime and removed comp: core labels Sep 7, 2016
@jamesmfriedman
Copy link
Author

@Andy1605 did you ever find a way around this? I kind of tabled working with NG2 because of this during the RCs. Would love to pick it back up, but this particular issue prevents me from building extensible UI patterns.

@jofran73
Copy link

I also feel that Angular is missing an essential feature here. It should be possible for a component to declare (multiple) attribute-directives for its host. Not being able to do that is a major hindrance for my project, too.
Does anybody know if this will be implemented in the future or if there are reasons why it cannot be done?

@Aaron-Pool
Copy link

I've proposed a solution to this issue (albeit for angular version 1) here: angular/angular.js#15270.

My idea is, instead of just having the ability to add directives, the compilation framework would have a new extensibility point called "hostTransforms" (in the case of angular 1, "nodeTransforms") which would have access to the unmodified, unfiltered component declaration and the original, uncompiled component host node whenever a component is first encountered by the compiler and being prepared for insertion into the DOM. This way a developer could extend component decorators with custom properties, and then use nodeTransforms to convert those custom properties into something the angular framework is familiar with, just before compilation. Check the feature request thread for examples.

I'm more familiar with the angular source code than the angular 2 source code, so I'm not sure if the implementation process would be the same here. But since this seems to be a pretty popular request, I'd love to see it either implemented in angular 2 and backported, or implemented in angularjs and forwardported (is that a thing?).

@oddlyfunctional
Copy link

+1

@jjstreet
Copy link

jjstreet commented Nov 1, 2016

I must agree, a feature that lets us add contributing attribute directives to the host would be great. I know I could use such a feature right now implementing a more "angular" like way adding drag/drop functionality to my UI components.

What about creating a new tag similar to <ng-container> that lets you apply them in the component's template instead of the host metadata property? Something like <ng-host [attributeDirective]> to indicate the directives are added to the host component.

@Aaron-Pool
Copy link

@jjstreet your proposal sounds similar to replace: true (obviously not identical, but similar), which was deprecated a while ago. But perhaps replace: true was deprecated for a reason that wouldn't apply here.

@pkozlowski-opensource Could we get a response of any kind from the ng2 team on this?

@jamesmfriedman
Copy link
Author

I'm game for any way to achieve this. I suggested the host property because it it has access to the local scope of the component, and it already adds attributes to the component itself. Directives seem like a natural extension of this behavior.

@k3nsei
Copy link

k3nsei commented Nov 14, 2016

+1 this feature is required to have clean and reusable code in UI components

@vlodko
Copy link

vlodko commented Dec 14, 2016

+1

@Aaron-Pool
Copy link

Could we please get some sort of response from the ng2 team on this? Even if it's just to say you're not going to do it, or to say it's a good idea but not a current priority, I'd just like to hear some sort of input.

@hccampos
Copy link

I'd like to add another use case for this. It would allow ng2-mobx (https://github.com/500tech/ng2-mobx) to get rid of the wrapping component and look much cleaner.

@klinki
Copy link

klinki commented Mar 9, 2017

I would love to have this too. Currently I need it to make custom routerLink directive. I'd love to reuse angular one and just provide it with parameters prepared by mi directive.

So instead of <a [routerLink]="repeatedCodeToGetLink()"> I would have <a [myRouterLink]> and it would dynamically apply [routerLink] with resolved parameters.

@somombo
Copy link

somombo commented Mar 30, 2017

Really excited about the prospects of this!

We have needed this for a while. In fact, a while back before I knew there was an open issue for it, I asked on stack overflow about essentially this very feature.

I have provided an elaborate example of how we'd be able to use this feature to solve angular/flex-layout#162 which we have had open for a while. (See the example and explanation here)

We are really looking forward to any feedback, I see that this issue is the third most thumbed-up of all open issues in this repo. Hopefully we can see this in the next release or sooner (fingers crossed)!

/cc @tbosch @IgorMinar @mhevery @jelbourn @hansl @ThomasBurleson

@somombo
Copy link

somombo commented Mar 30, 2017

@jjstreet I think your suggestion

<ng-host myDirective="foo"></ng-host> 

... would go well with another separate proposal that was made a while back for seperate reasons than we are discussing here.

See #7297

@fadzic
Copy link

fadzic commented Apr 4, 2017

Currently I work around this by adding directive in the parent component and then add listener in the host with the @HostListener.

Parent.html
<my-component myDirective>

Component.ts
@HostListener('myEvent') handler() { // do stuff }

But it would be cleaner if we can add attributes directly in the host...

@somombo
Copy link

somombo commented Apr 7, 2017

Here is how I have been dealing with this, but I really think implementing this feature from the ground would be the best solution.

@Aaron-Pool
Copy link

Just a monthly reminder that we're waiting for positive or negative comment on this from the Angular team.

@ThomasBurleson
Copy link

@tbosch - Any public thoughts on the priority of this issue. It also impacts @angular/flex-layout.

@ghost
Copy link

ghost commented May 2, 2017

@fadzic can you not just add the directive to the host element by doing this...

Component.ts
@HostBinding('attr.myHilite') myHilite = new myHiliteDirective()

or like this if you need parameters like ElementRef or Renderer2
@HostBinding('attr.myHilite') myHilite = new myHiliteDirective(this.elementRef, this.renderer)

I also have the need to add a directive to the host element and I was redirected to this issue. I was able to do what I needed using the code above. I am in no way an expert using angular but this workaround seems to work so far, if someone had issues with this approach let me know. Thanks.

@hccampos
Copy link

hccampos commented May 2, 2017

@btinoco that doesn't work because no lifecycle methods get called. You'd have to manually wire everything up in each component that uses the directive rather than just having Angular wire it up for you.

@ghost
Copy link

ghost commented May 2, 2017

@hccampos thanks for the heads up. I have just tried it and the ngOnInit of my directive did not execute (unless I use the directive in my component manually) or I call the directive's ngOnInit() on my component'sngOnInit(). Again thank you for letting me know that.

@nartc
Copy link
Contributor

nartc commented Jul 19, 2022

Moved from PR

@crisbeto thank you for the response. I figured it'd be the case. In that case, should we update the PR description to call it out for Structural Directives? I guess it makes sense that this feature only targets Attribute Directive. Structural should be handled on the consuming (component's users) side of things rather than authoring (component's author).

Question 1: is it possible to have TypeScript generics supported?

@Directive()
export abstract class NgtInstance<TObject> {
   @Output() ready = new EventEmitter<TObject>();
}

@Component()
export class NgtMesh extends NgtInstance<THREE.Mesh> {}

Here's a sample inheritance example. In reality, the inheritance level might be more than 1 level deep. You can see here that I can have generics with inheritance, and (ready) is strongly typed to THREE.Mesh

Let's try with Directive Composition

@Directive({
   selector: '[ngt-instance]'
   standalone: true
})
export class NgtInstance<TObject> {
   @Output() ready = new EventEmitter<TObject>();
}

@Component({
   hostDirectives: [
      // not sure how to provide THREE.Mesh here for (ready) to be strongly typed
      // maybe something like NgtInstance as NgtInstance<THREE.Mesh> and the compiler can figure it out?
      { directive: NgtInstance, outputs: ['ready'] }
   ]
})
export class NgtMesh {}

Question 2: assuming everything is standalone, where do we import the Host Directives?

@Component({
  hostDirectives: [DirectiveA, {directive: DirectiveB, inputs: ['foo: fooAlias'], outputs: ['bar']}]
})

based on this example, where do we import DirectiveA and DirectiveB?

@crisbeto
Copy link
Member

Regarding structural directives: I'm not sure why they need to be called out specifically. You can still apply a host directive to them, but it's going to work on the template instance, the same as if you were to apply a directive to the ng-template.

Regarding generics: this is one of the limitations we are aware of, but I'm not sure if there's a good way around it given that the host directives are referenced by value. We could introduce some way of inferring the generic type in the future, but it's not something we've considered yet for v1.

Regarding the standalone question: only the directives referenced in the hostDirectives array have to be standalone, the host itself can be imported into an NgModule, or it can standalone itself. In your example, DirectiveA and DirectiveB are standalone so they wouldn't need to be imported anywhere.

@nartc
Copy link
Contributor

nartc commented Jul 19, 2022

@crisbeto I just realized that we can probably have selector: ng-template[component-selector] and structural directive would work.

Thanks for the concise answers.

@Harpush
Copy link

Harpush commented Jul 19, 2022

@crisbeto Regarding genrics - won't Instantiation expressions solve it somehow?

@crisbeto
Copy link
Member

@Harpush do you mean something like hostDirectives: [new HostDir<T>()]? I don't think that'll work. One possibility is to use a cast (e.g. hostDirectives: [HostDir as HostDir<T>], but that might be weird as well.

@Harpush
Copy link

Harpush commented Jul 19, 2022

@crisbeto I meant the new typescript 4.7 feature allowing to assign generic params without new.
For example:

const Component = <T>() => ({hostDirectives: [HostDir<T>]});

That is assuming you somehow have access to that T which seems like the real problem here (decorator can't access class generic params afaik).
But considering T is known at compile time this should work I think?

hostDirectives: [HostDir<number>]

@crisbeto
Copy link
Member

Ah, then me way be able to get it to work since the compiler should have access to the generic type. I would still defer this for after the initial implementation is done.

crisbeto added a commit to crisbeto/angular that referenced this issue Jul 23, 2022
This is the compile-time implementation of the `hostDirectives` feature plus a little bit of runtime code to illustrate how the newly-generated code will plug into the runtime. It works by creating a call to the new `ɵɵHostDirectivesFeature` feature whenever a directive has a `hostDirectives` field. Afterwards `ɵɵHostDirectivesFeature` will patch a new function onto the directive definition that will be invoked during directive matching.

For example, if we take the following definition:

```ts
@directive({
  hostDirectives: [HostA, {directive: HostB, inputs: ['input: alias']}]
})
class MyDir {}
```

Will compile to:

```js
MyDir.ɵdir = ɵɵdefineComponent({
  features: [ɵɵHostDirectivesFeature([HostA, {
    directive: HostB,
    inputs: {
      input: "alias"
    }
  }])]
});
```

The template type checking is implemented during directive matching by adding the host directives applied on the host to the array of matched directives whenever the host is matched in a template.

Relates to angular#8785.
crisbeto added a commit to crisbeto/angular that referenced this issue Aug 1, 2022
This is the compile-time implementation of the `hostDirectives` feature plus a little bit of runtime code to illustrate how the newly-generated code will plug into the runtime. It works by creating a call to the new `ɵɵHostDirectivesFeature` feature whenever a directive has a `hostDirectives` field. Afterwards `ɵɵHostDirectivesFeature` will patch a new function onto the directive definition that will be invoked during directive matching.

For example, if we take the following definition:

```ts
@directive({
  hostDirectives: [HostA, {directive: HostB, inputs: ['input: alias']}]
})
class MyDir {}
```

Will compile to:

```js
MyDir.ɵdir = ɵɵdefineComponent({
  features: [ɵɵHostDirectivesFeature([HostA, {
    directive: HostB,
    inputs: {
      input: "alias"
    }
  }])]
});
```

The template type checking is implemented during directive matching by adding the host directives applied on the host to the array of matched directives whenever the host is matched in a template.

Relates to angular#8785.
crisbeto added a commit to crisbeto/angular that referenced this issue Aug 3, 2022
This is the compile-time implementation of the `hostDirectives` feature plus a little bit of runtime code to illustrate how the newly-generated code will plug into the runtime. It works by creating a call to the new `ɵɵHostDirectivesFeature` feature whenever a directive has a `hostDirectives` field. Afterwards `ɵɵHostDirectivesFeature` will patch a new function onto the directive definition that will be invoked during directive matching.

For example, if we take the following definition:

```ts
@directive({
  hostDirectives: [HostA, {directive: HostB, inputs: ['input: alias']}]
})
class MyDir {}
```

Will compile to:

```js
MyDir.ɵdir = ɵɵdefineComponent({
  features: [ɵɵHostDirectivesFeature([HostA, {
    directive: HostB,
    inputs: {
      input: "alias"
    }
  }])]
});
```

The template type checking is implemented during directive matching by adding the host directives applied on the host to the array of matched directives whenever the host is matched in a template.

Relates to angular#8785.
crisbeto added a commit to crisbeto/angular that referenced this issue Aug 9, 2022
This is the compile-time implementation of the `hostDirectives` feature plus a little bit of runtime code to illustrate how the newly-generated code will plug into the runtime. It works by creating a call to the new `ɵɵHostDirectivesFeature` feature whenever a directive has a `hostDirectives` field. Afterwards `ɵɵHostDirectivesFeature` will patch a new function onto the directive definition that will be invoked during directive matching.

For example, if we take the following definition:

```ts
@directive({
  hostDirectives: [HostA, {directive: HostB, inputs: ['input: alias']}]
})
class MyDir {}
```

Will compile to:

```js
MyDir.ɵdir = ɵɵdefineComponent({
  features: [ɵɵHostDirectivesFeature([HostA, {
    directive: HostB,
    inputs: {
      input: "alias"
    }
  }])]
});
```

The template type checking is implemented during directive matching by adding the host directives applied on the host to the array of matched directives whenever the host is matched in a template.

Relates to angular#8785.
crisbeto added a commit to crisbeto/angular that referenced this issue Aug 12, 2022
This is the compile-time implementation of the `hostDirectives` feature plus a little bit of runtime code to illustrate how the newly-generated code will plug into the runtime. It works by creating a call to the new `ɵɵHostDirectivesFeature` feature whenever a directive has a `hostDirectives` field. Afterwards `ɵɵHostDirectivesFeature` will patch a new function onto the directive definition that will be invoked during directive matching.

For example, if we take the following definition:

```ts
@directive({
  hostDirectives: [HostA, {directive: HostB, inputs: ['input: alias']}]
})
class MyDir {}
```

Will compile to:

```js
MyDir.ɵdir = ɵɵdefineComponent({
  features: [ɵɵHostDirectivesFeature([HostA, {
    directive: HostB,
    inputs: {
      input: "alias"
    }
  }])]
});
```

The template type checking is implemented during directive matching by adding the host directives applied on the host to the array of matched directives whenever the host is matched in a template.

Relates to angular#8785.
crisbeto added a commit to crisbeto/angular that referenced this issue Aug 15, 2022
This is the compile-time implementation of the `hostDirectives` feature plus a little bit of runtime code to illustrate how the newly-generated code will plug into the runtime. It works by creating a call to the new `ɵɵHostDirectivesFeature` feature whenever a directive has a `hostDirectives` field. Afterwards `ɵɵHostDirectivesFeature` will patch a new function onto the directive definition that will be invoked during directive matching.

For example, if we take the following definition:

```ts
@directive({
  hostDirectives: [HostA, {directive: HostB, inputs: ['input: alias']}]
})
class MyDir {}
```

Will compile to:

```js
MyDir.ɵdir = ɵɵdefineComponent({
  features: [ɵɵHostDirectivesFeature([HostA, {
    directive: HostB,
    inputs: {
      input: "alias"
    }
  }])]
});
```

The template type checking is implemented during directive matching by adding the host directives applied on the host to the array of matched directives whenever the host is matched in a template.

Relates to angular#8785.
crisbeto added a commit to crisbeto/angular that referenced this issue Aug 16, 2022
This is the compile-time implementation of the `hostDirectives` feature plus a little bit of runtime code to illustrate how the newly-generated code will plug into the runtime. It works by creating a call to the new `ɵɵHostDirectivesFeature` feature whenever a directive has a `hostDirectives` field. Afterwards `ɵɵHostDirectivesFeature` will patch a new function onto the directive definition that will be invoked during directive matching.

For example, if we take the following definition:

```ts
@directive({
  hostDirectives: [HostA, {directive: HostB, inputs: ['input: alias']}]
})
class MyDir {}
```

Will compile to:

```js
MyDir.ɵdir = ɵɵdefineComponent({
  features: [ɵɵHostDirectivesFeature([HostA, {
    directive: HostB,
    inputs: {
      input: "alias"
    }
  }])]
});
```

The template type checking is implemented during directive matching by adding the host directives applied on the host to the array of matched directives whenever the host is matched in a template.

Relates to angular#8785.
crisbeto added a commit to crisbeto/angular that referenced this issue Aug 19, 2022
This is the compile-time implementation of the `hostDirectives` feature plus a little bit of runtime code to illustrate how the newly-generated code will plug into the runtime. It works by creating a call to the new `ɵɵHostDirectivesFeature` feature whenever a directive has a `hostDirectives` field. Afterwards `ɵɵHostDirectivesFeature` will patch a new function onto the directive definition that will be invoked during directive matching.

For example, if we take the following definition:

```ts
@directive({
  hostDirectives: [HostA, {directive: HostB, inputs: ['input: alias']}]
})
class MyDir {}
```

Will compile to:

```js
MyDir.ɵdir = ɵɵdefineComponent({
  features: [ɵɵHostDirectivesFeature([HostA, {
    directive: HostB,
    inputs: {
      input: "alias"
    }
  }])]
});
```

The template type checking is implemented during directive matching by adding the host directives applied on the host to the array of matched directives whenever the host is matched in a template.

Relates to angular#8785.
crisbeto added a commit to crisbeto/angular that referenced this issue Aug 22, 2022
This is the compile-time implementation of the `hostDirectives` feature plus a little bit of runtime code to illustrate how the newly-generated code will plug into the runtime. It works by creating a call to the new `ɵɵHostDirectivesFeature` feature whenever a directive has a `hostDirectives` field. Afterwards `ɵɵHostDirectivesFeature` will patch a new function onto the directive definition that will be invoked during directive matching.

For example, if we take the following definition:

```ts
@directive({
  hostDirectives: [HostA, {directive: HostB, inputs: ['input: alias']}]
})
class MyDir {}
```

Will compile to:

```js
MyDir.ɵdir = ɵɵdefineComponent({
  features: [ɵɵHostDirectivesFeature([HostA, {
    directive: HostB,
    inputs: {
      input: "alias"
    }
  }])]
});
```

The template type checking is implemented during directive matching by adding the host directives applied on the host to the array of matched directives whenever the host is matched in a template.

Relates to angular#8785.
alxhub pushed a commit that referenced this issue Aug 22, 2022
This is the compile-time implementation of the `hostDirectives` feature plus a little bit of runtime code to illustrate how the newly-generated code will plug into the runtime. It works by creating a call to the new `ɵɵHostDirectivesFeature` feature whenever a directive has a `hostDirectives` field. Afterwards `ɵɵHostDirectivesFeature` will patch a new function onto the directive definition that will be invoked during directive matching.

For example, if we take the following definition:

```ts
@directive({
  hostDirectives: [HostA, {directive: HostB, inputs: ['input: alias']}]
})
class MyDir {}
```

Will compile to:

```js
MyDir.ɵdir = ɵɵdefineComponent({
  features: [ɵɵHostDirectivesFeature([HostA, {
    directive: HostB,
    inputs: {
      input: "alias"
    }
  }])]
});
```

The template type checking is implemented during directive matching by adding the host directives applied on the host to the array of matched directives whenever the host is matched in a template.

Relates to #8785.

PR Close #46868
@framasev
Copy link

Have you considered using a @HostDirective decorator and augmenting a directive through decorators composition?

@HostDirective(FooDirective)
@Component()
class FooComponent {}

@HostDirective(FooDirective)
@Directive()
class BarDirective {}

@HostDirective(DirectiveA)
@HostDirective(DirectiveB)
@Directive()
class DirectiveC {}

@crisbeto crisbeto modified the milestones: Backlog, v15 Feature Freeze Sep 12, 2022
crisbeto added a commit to crisbeto/angular that referenced this issue Oct 5, 2022
Enables the new directive composition API by exposing the `hostDirectives` property on the `Directive` and `Component` decorators. Also cleans up some casts that were put in place while the feature was being developed.

Fixes angular#8785.
@johncrim
Copy link

johncrim commented Nov 3, 2022

@crisbeto - This is an amazing addition to angular, thank you very much. I'll be porting our component libraries to use it, I look forward to the improvements in code simplicity and code size.

@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 Dec 4, 2022
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 core: host and host bindings feature: under consideration Feature request for which voting has completed and the request is now under consideration feature Issue that requests a new feature state: has PR
Projects
None yet
Development

Successfully merging a pull request may close this issue.