mirror of
https://github.com/angular/angular
synced 2026-05-24 09:28:37 +00:00
refactor(compiler): element references not resolved when selectorless matcher is passed in (#61100)
Fixes that the template binder didn't resolve references to DOM nodes (e.g. `<div #ref></div>` if the matcher being passed in isn't a `SelectorMatcher`. PR Close #61100
This commit is contained in:
parent
7d2a6b3864
commit
2c17145520
2 changed files with 39 additions and 13 deletions
|
|
@ -203,17 +203,15 @@ export class R3TargetBinder<DirectiveT extends DirectiveMeta> implements TargetB
|
|||
// - bindings: Map of inputs, outputs, and attributes to the directive/element that claims
|
||||
// them. TODO(alxhub): handle multiple directives claiming an input/output/etc.
|
||||
// - references: Map of #references to their targets.
|
||||
if (this.directiveMatcher !== null) {
|
||||
DirectiveBinder.apply(
|
||||
target.template,
|
||||
this.directiveMatcher,
|
||||
directives,
|
||||
eagerDirectives,
|
||||
missingDirectives,
|
||||
bindings,
|
||||
references,
|
||||
);
|
||||
}
|
||||
DirectiveBinder.apply(
|
||||
target.template,
|
||||
this.directiveMatcher,
|
||||
directives,
|
||||
eagerDirectives,
|
||||
missingDirectives,
|
||||
bindings,
|
||||
references,
|
||||
);
|
||||
|
||||
// Finally, run the TemplateBinder to bind references, variables, and other entities within the
|
||||
// template. This extracts all the metadata that doesn't depend on directive matching.
|
||||
|
|
@ -502,7 +500,7 @@ class DirectiveBinder<DirectiveT extends DirectiveMeta> implements Visitor {
|
|||
private isInDeferBlock = false;
|
||||
|
||||
private constructor(
|
||||
private directiveMatcher: DirectiveMatcher<DirectiveT>,
|
||||
private directiveMatcher: DirectiveMatcher<DirectiveT> | null,
|
||||
private directives: MatchedDirectives<DirectiveT>,
|
||||
private eagerDirectives: DirectiveT[],
|
||||
private missingDirectives: Set<string>,
|
||||
|
|
@ -524,7 +522,7 @@ class DirectiveBinder<DirectiveT extends DirectiveMeta> implements Visitor {
|
|||
*/
|
||||
static apply<DirectiveT extends DirectiveMeta>(
|
||||
template: Node[],
|
||||
directiveMatcher: DirectiveMatcher<DirectiveT>,
|
||||
directiveMatcher: DirectiveMatcher<DirectiveT> | null,
|
||||
directives: MatchedDirectives<DirectiveT>,
|
||||
eagerDirectives: DirectiveT[],
|
||||
missingDirectives: Set<string>,
|
||||
|
|
@ -642,6 +640,12 @@ class DirectiveBinder<DirectiveT extends DirectiveMeta> implements Visitor {
|
|||
const cssSelector = createCssSelectorFromNode(node);
|
||||
this.directiveMatcher.match(cssSelector, (_, results) => directives.push(...results));
|
||||
this.trackSelectorBasedBindingsAndDirectives(node, directives);
|
||||
} else {
|
||||
node.references.forEach((ref) => {
|
||||
if (ref.value.trim() === '') {
|
||||
this.references.set(ref, node);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
node.directives.forEach((directive) => directive.visit(this));
|
||||
|
|
|
|||
|
|
@ -443,6 +443,17 @@ describe('t2 binding', () => {
|
|||
expect(res.getDefinitionNodeOfSymbol(secondLet)).toBe(secondBranch);
|
||||
});
|
||||
|
||||
it('should resolve an element reference without a directive matcher', () => {
|
||||
const template = parseTemplate('<div #foo></div>', '');
|
||||
const binder = new R3TargetBinder(null);
|
||||
const res = binder.bind({template: template.nodes});
|
||||
const node = template.nodes[0] as a.Component;
|
||||
const reference = node.references[0];
|
||||
const result = res.getReferenceTarget(reference) as a.Element;
|
||||
expect(result instanceof a.Element).toBe(true);
|
||||
expect(result.name).toBe('div');
|
||||
});
|
||||
|
||||
describe('matching inputs to consuming directives', () => {
|
||||
it('should work for bound attributes', () => {
|
||||
const template = parseTemplate('<div hasInput [inputBinding]="myValue"></div>', '', {});
|
||||
|
|
@ -1170,6 +1181,17 @@ describe('t2 binding', () => {
|
|||
expect(result.directive.name).toBe('Dir');
|
||||
});
|
||||
|
||||
it('should resolve a reference on an element when using a selectorless matcher', () => {
|
||||
const template = parseTemplate('<div #foo></div>', '', options);
|
||||
const binder = new R3TargetBinder(makeSelectorlessMatcher([]));
|
||||
const res = binder.bind({template: template.nodes});
|
||||
const node = template.nodes[0] as a.Component;
|
||||
const reference = node.references[0];
|
||||
const result = res.getReferenceTarget(reference) as a.Element;
|
||||
expect(result instanceof a.Element).toBe(true);
|
||||
expect(result.name).toBe('div');
|
||||
});
|
||||
|
||||
it('should get consumer of component bindings', () => {
|
||||
const template = parseTemplate(
|
||||
'<MyComp [input]="value" static="value" (output)="doStuff()" [doesNotExist]="value" [attr.input]="value"/>',
|
||||
|
|
|
|||
Loading…
Reference in a new issue