feat(ivy): separate attributes for directive matching purposes (#23991)

In ngIvy directives matching (determining which directives are active based
on a CSS seletor) happens at runtime. This means that runtime needs to have
enough context to match directives. This PR takes care of cases where a directive's
selector should match bindings (ex. [foo]="exp") and event handlers (ex. (out)="do()").
In the mentioned cases we need to have binding / output "attributes" for directive's
CSS selector matching purposes. At the same time those are not regular attributes and
as such should not  be reflected in the DOM.

Closes #23706

PR Close #23991
This commit is contained in:
Pawel Kozlowski
2018-05-04 15:58:42 +02:00
committed by Victor Berchet
parent b87d650da2
commit 90bf5d8961
9 changed files with 349 additions and 74 deletions

View File

@ -22,7 +22,7 @@ import {assertGreaterThan, assertLessThan, assertNotNull} from './assert';
import {addToViewTree, assertPreviousIsParent, createLContainer, createLNodeObject, createTNode, createTView, getDirectiveInstance, getPreviousOrParentNode, getRenderer, isComponent, renderEmbeddedTemplate, resolveDirective} from './instructions';
import {ComponentTemplate, DirectiveDef, DirectiveDefList, PipeDefList} from './interfaces/definition';
import {LInjector} from './interfaces/injector';
import {LContainerNode, LElementNode, LNode, LViewNode, TNodeFlags, TNodeType} from './interfaces/node';
import {AttributeMarker, LContainerNode, LElementNode, LNode, LViewNode, TNodeFlags, TNodeType} from './interfaces/node';
import {QueryReadType} from './interfaces/query';
import {Renderer3} from './interfaces/renderer';
import {LView, TView} from './interfaces/view';
@ -251,7 +251,7 @@ export function injectChangeDetectorRef(): viewEngine_ChangeDetectorRef {
*
* @experimental
*/
export function injectAttribute(attrName: string): string|undefined {
export function injectAttribute(attrNameToInject: string): string|undefined {
ngDevMode && assertPreviousIsParent();
const lElement = getPreviousOrParentNode() as LElementNode;
ngDevMode && assertNodeType(lElement, TNodeType.Element);
@ -260,8 +260,10 @@ export function injectAttribute(attrName: string): string|undefined {
const attrs = tElement.attrs;
if (attrs) {
for (let i = 0; i < attrs.length; i = i + 2) {
if (attrs[i] == attrName) {
return attrs[i + 1];
const attrName = attrs[i];
if (attrName === AttributeMarker.SELECT_ONLY) break;
if (attrName == attrNameToInject) {
return attrs[i + 1] as string;
}
}
}