Skip to content

Commit 17c110e

Browse files
committed
refactor(compiler): allow directives to be resolved on host element (#62965)
Allows the target binder to resolve directives set on the host element. PR Close #62965
1 parent e0d436a commit 17c110e

File tree

2 files changed

+17
-12
lines changed

2 files changed

+17
-12
lines changed

packages/compiler/src/render3/view/t2_api.ts

Lines changed: 9 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -48,15 +48,15 @@ export type ScopedNode =
4848

4949
/** Possible values that a reference can be resolved to. */
5050
export type ReferenceTarget<DirectiveT> =
51-
| {directive: DirectiveT; node: DirectiveOwner}
51+
| {directive: DirectiveT; node: Exclude<DirectiveOwner, HostElement>}
5252
| Element
5353
| Template;
5454

5555
/** Entity that is local to the template and defined within the template. */
5656
export type TemplateEntity = Reference | Variable | LetDeclaration;
5757

5858
/** Nodes that can have directives applied to them. */
59-
export type DirectiveOwner = Element | Template | Component | Directive;
59+
export type DirectiveOwner = Element | Template | Component | Directive | HostElement;
6060

6161
/*
6262
* t2 is the replacement for the `TemplateDefinitionBuilder`. It handles the operations of
@@ -70,9 +70,12 @@ export type DirectiveOwner = Element | Template | Component | Directive;
7070
/**
7171
* A logical target for analysis, which could contain a template or other types of bindings.
7272
*/
73-
export interface Target {
73+
export interface Target<DirectiveT> {
7474
template?: Node[];
75-
host?: HostElement;
75+
host?: {
76+
node: HostElement;
77+
directives: DirectiveT[];
78+
};
7679
}
7780

7881
/**
@@ -162,7 +165,7 @@ export interface DirectiveMeta {
162165
* The returned `BoundTarget` has an API for extracting information about the processed target.
163166
*/
164167
export interface TargetBinder<D extends DirectiveMeta> {
165-
bind(target: Target): BoundTarget<D>;
168+
bind(target: Target<D>): BoundTarget<D>;
166169
}
167170

168171
/**
@@ -177,7 +180,7 @@ export interface BoundTarget<DirectiveT extends DirectiveMeta> {
177180
/**
178181
* Get the original `Target` that was bound.
179182
*/
180-
readonly target: Target;
183+
readonly target: Target<DirectiveT>;
181184

182185
/**
183186
* For a given template node (either an `Element` or a `Template`), get the set of directives

packages/compiler/src/render3/view/t2_binder.ts

Lines changed: 8 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -84,7 +84,7 @@ type BindingsMap<DirectiveT> = Map<
8484
/** Shorthand for a map between a reference AST node and the entity it's targeting. */
8585
type ReferenceMap<DirectiveT> = Map<
8686
Reference,
87-
Template | Element | {directive: DirectiveT; node: DirectiveOwner}
87+
Template | Element | {directive: DirectiveT; node: Exclude<DirectiveOwner, HostElement>}
8888
>;
8989

9090
/** Mapping between AST nodes and the directives that have been matched on them. */
@@ -171,7 +171,7 @@ export class R3TargetBinder<DirectiveT extends DirectiveMeta> implements TargetB
171171
* Perform a binding operation on the given `Target` and return a `BoundTarget` which contains
172172
* metadata about the types referenced in the template.
173173
*/
174-
bind(target: Target): BoundTarget<DirectiveT> {
174+
bind(target: Target<DirectiveT>): BoundTarget<DirectiveT> {
175175
if (!target.template && !target.host) {
176176
throw new Error('Empty bound targets are not supported');
177177
}
@@ -229,9 +229,10 @@ export class R3TargetBinder<DirectiveT extends DirectiveMeta> implements TargetB
229229
// Bind the host element in a separate scope. Note that it only uses the
230230
// `TemplateBinder` since directives don't apply inside a host context.
231231
if (target.host) {
232+
directives.set(target.host.node, target.host.directives);
232233
TemplateBinder.applyWithScope(
233-
target.host,
234-
Scope.apply(target.host),
234+
target.host.node,
235+
Scope.apply(target.host.node),
235236
expressions,
236237
symbols,
237238
nestingLevel,
@@ -1029,7 +1030,7 @@ class R3BoundTarget<DirectiveT extends DirectiveMeta> implements BoundTarget<Dir
10291030
private deferredScopes: Map<DeferredBlock, Scope>;
10301031

10311032
constructor(
1032-
readonly target: Target,
1033+
readonly target: Target<DirectiveT>,
10331034
private directives: MatchedDirectives<DirectiveT>,
10341035
private eagerDirectives: DirectiveT[],
10351036
private missingDirectives: Set<string>,
@@ -1217,7 +1218,8 @@ class R3BoundTarget<DirectiveT extends DirectiveMeta> implements BoundTarget<Dir
12171218
if (
12181219
target instanceof Template ||
12191220
target.node instanceof Component ||
1220-
target.node instanceof Directive
1221+
target.node instanceof Directive ||
1222+
target.node instanceof HostElement
12211223
) {
12221224
return null;
12231225
}

0 commit comments

Comments
 (0)