diff --git a/packages/core/src/render3/node_selector_matcher.ts b/packages/core/src/render3/node_selector_matcher.ts
index d4af2755cf..3806ce0418 100644
--- a/packages/core/src/render3/node_selector_matcher.ts
+++ b/packages/core/src/render3/node_selector_matcher.ts
@@ -37,18 +37,19 @@ function isCssClassMatching(nodeClassAttrVal: string, cssClassToMatch: string):
* Function that checks whether a given tNode matches tag-based selector and has a valid type.
*
* Matching can be performed in 2 modes: projection mode (when we project nodes) and regular
- * directive matching mode. In "projection" mode, we do not need to check types, so if tag name
- * matches selector, we declare a match. In "directive matching" mode, we also check whether tNode
- * is of expected type:
- * - whether tNode has either Element or ElementContainer type
- * - or if we want to match "ng-template" tag, we check for Container type
+ * directive matching mode:
+ * - in the "directive matching" mode we do _not_ take TContainer's tagName into account if it is
+ * different from NG_TEMPLATE_SELECTOR (value different from NG_TEMPLATE_SELECTOR indicates that a
+ * tag name was extracted from * syntax so we would match the same directive twice);
+ * - in the "projection" mode, we use a tag name potentially extracted from the * syntax processing
+ * (applicable to TNodeType.Container only).
*/
function hasTagAndTypeMatch(
tNode: TNode, currentSelector: string, isProjectionMode: boolean): boolean {
- return currentSelector === tNode.tagName &&
- (isProjectionMode ||
- (tNode.type === TNodeType.Element || tNode.type === TNodeType.ElementContainer) ||
- (tNode.type === TNodeType.Container && currentSelector === NG_TEMPLATE_SELECTOR));
+ const tagNameToCompare = tNode.type === TNodeType.Container && !isProjectionMode ?
+ NG_TEMPLATE_SELECTOR :
+ tNode.tagName;
+ return currentSelector === tagNameToCompare;
}
/**
diff --git a/packages/core/test/acceptance/directive_spec.ts b/packages/core/test/acceptance/directive_spec.ts
new file mode 100644
index 0000000000..65defd2b80
--- /dev/null
+++ b/packages/core/test/acceptance/directive_spec.ts
@@ -0,0 +1,47 @@
+/**
+ * @license
+ * Copyright Google Inc. All Rights Reserved.
+ *
+ * Use of this source code is governed by an MIT-style license that can be
+ * found in the LICENSE file at https://angular.io/license
+ */
+
+import {Component, Directive} from '@angular/core';
+import {TestBed} from '@angular/core/testing';
+import {By} from '@angular/platform-browser';
+
+describe('directives', () => {
+
+ describe('matching', () => {
+
+ @Directive({selector: 'ng-template[test]'})
+ class TestDirective {
+ }
+
+ @Component({selector: 'test-cmpt', template: ''})
+ class TestComponent {
+ }
+
+ it('should match directives on ng-template', () => {
+ TestBed.configureTestingModule({declarations: [TestComponent, TestDirective]});
+ TestBed.overrideTemplate(TestComponent, `