Goal:
Provide 'synonym' selectors for components and directives within my application.
Motivation:
There are times where a component or directive provides functionality that can be thought of in different ways whereas the name of the selector should meaningfully represent or simplify thinking about how the component or directive operates (the name being a mnemonic device).
Research:
I had observed that Material 2 provides what seemed to be multiple selectors for its MdList
and MdListItem
directives:
https://github.com/angular/material2/blob/master/src/lib/list/list.ts
@Component({
moduleId: module.id,
selector: 'md-list, md-nav-list',
host: {'role': 'list'},
template: '<ng-content></ng-content>',
styleUrls: ['list.css'],
encapsulation: ViewEncapsulation.None
})
export class MdList {}
...and...
@Component({
moduleId: module.id,
selector: 'md-list-item, a[md-list-item]',
host: {
'role': 'listitem',
'(focus)': '_handleFocus()',
'(blur)': '_handleBlur()',
},
templateUrl: 'list-item.html',
encapsulation: ViewEncapsulation.None
})
export class MdListItem implements AfterContentInit {
...
}
From the Angular 2 attribute directives page in the documentation:
https://angular.io/docs/ts/latest/guide/attribute-directives.html
@Directive
requires a CSS selector to identify the HTML in the template that is associated with our directive. The CSS selector for an attribute is the attribute name in square brackets. Our directive's selector is[myHighlight]
. Angular will locate all elements in the template that have an attribute namedmyHighlight
.
Which links to the following attribute selectors MDN page:
https://developer.mozilla.org/en-US/docs/Web/CSS/Attribute_selectors
From the Angular 2 Cheat Sheet page:
https://angular.io/docs/js/latest/guide/cheatsheet.html
The comma syntax of the Material 2 list.ts
CSS selectors that I found, suggests that these apply to multiple situations - my evaluation of what these selectors are doing is:
class MdList
applies to md-list
and md-nav-list
elementsclass MdListItem
applies to md-list-item
and a
elements that have a md-list-item
attributeFrom the Angular 2 Architecture Overview page:
https://angular.io/docs/ts/latest/guide/architecture.html
selector: CSS selector that tells Angular to create and insert an instance of this component where it finds a
<hero-list>
tag in parent HTML. For example, if an app's HTML contains<hero-list></hero-list>
, then Angular inserts an instance of theHeroListComponent
view between those tags.`
Interestingly, in the wild, I have not come across any example of a component that has multiple selectors.
Mental Model Misconceptions:
When I was introduced to Angular 2 I "lazily" interpreted selectors
merely as the name of the component or directive as represented within the application HTML
.
In my (faulty) mental model component selectors where only a way of effectively defining an application specific HTML
element.
In my (faulty) mental model directive selectors where only a way to define an application specific HTML
element attribute serving to modify the behavior of the element.
Having done the research and having carefully studied (all of the words in) the documentation I have come to realize that there's something more powerful going on here...
General Questions:
Specific Questions:
With , separated multiple selectors can be used where the component is added to elements where one of these matches. Many of Angulars built-in directives use a list of selectors.
A selector is used to identify each component uniquely into the component tree, and it also defines how the current component is represented in the HTML DOM. When we create a new component using Angular CLI, the newly created component looks like this.
Two or more components use the same element selector. Because there can only be a single component associated with an element, selectors must be unique strings to prevent ambiguity for Angular.
You can not use two structural directives on the same element. You need to wrap your element in another one. It's advised to use ng-container since it wont be rendered in DOM.
Where have I got any of the above wrong?
"lazily" interpreted selectors
I don't know about lazily interpreted selectors.
If a tag that matches a selector or a component is found in a components template, then it is upgraded to an Angular component.
If ViewContainerRef.createComponent()
is used (like the router does) to add a component dynamically, then a tag that matches the selector is added to the DOM and the component applied to it.
In my (faulty) mental model component selectors where only a way of effectively defining an application specific HTML element.
Selectors are for matching a DOM element with a component or directive for Angular to know what part of the DOM should become a component or directive.
What other aspects of component and directive selectors am I missing? e.g. is there more power to be harnessed here?
Can a component have element attribute selector? and if so, what would the behavior/effect be?
You can use custom tag names, attributes, and CSS classes and any combination of these. You can't use id
or selectors that span multiple elements. With ,
separated multiple selectors can be used where the component is added to elements where one of these matches.
Many of Angulars built-in directives use a list of selectors.
In which situations would you want a directive to have an element selector?
A directive is the same as a component, just without it's own view.
<my-dropdown>
<my-item></my-item>
<my-item></my-item>
<my-item></my-item>
</my-dropdown>
Could be implemented by a component like
@Component({
selector: 'my-dropdown',
template: '<ng-content></ng-content>'
})
or
@Directive({
selector: 'my-dropdown',
})
and they would do exactly the same.
What's the syntax to apply a directive to synonym CSS attributes? e.g. apply a directive to any of a group of CSS attribute selectors...
selector: '[attr1],[attr2],[attr3]'
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With