Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to define an Angular 2 component or directive with multiple selectors

Tags:

css

angular

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:

Directives

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 named myHighlight.

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

enter image description here


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:

  1. class MdList applies to md-list and md-nav-list elements
  2. class MdListItem applies to md-list-item and a elements that have a md-list-item attribute

Components

From 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 the HeroListComponent 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:

  1. Where have I got any of the above wrong?
  2. What other aspects of component and directive selectors am I missing? e.g. is there more power to be harnessed here?

Specific Questions:

  1. Can a component have element attribute selector? and if so, what would the behavior/effect be?
  2. In which situations would you want a directive to have an element selector?
  3. 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...
like image 214
Neoheurist Avatar asked Sep 09 '16 14:09

Neoheurist


People also ask

Can Angular component have multiple selectors?

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.

What is the purpose of the selector property when defining an Angular 2 component?

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.

Can two components have same selector?

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.

Can we use multiple directives in 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.


1 Answers

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]'
like image 129
Günter Zöchbauer Avatar answered Oct 12 '22 10:10

Günter Zöchbauer