Component#selector
and Directive#selector
are just like CSS Selector. This means we can utilize some CSS pseudo-class to put constraints on our selector
, making them more robust and provide better DX to our consumers
Suppose we have the following NgxLilGui
component that wraps the lil-gui
library.
To learn more about
lil-gui
, visit https://lil-gui.georgealways.com/
@Component({
selector: "ngx-lil-gui",
template: ` <ng-content></ng-content> `,
standalone: true,
})
export class NgxLilGui implements OnInit, OnDestroy {
@Input() config: Config;
@Input() object: Record<string, any>;
/* ... */
}
To make it flexible for the consumers, we allow the consumers to use config
OR object
to control the lil-gui
library. In addition, the consumers can also use <ngx-lil-gui>
without passing in anything. In this case, <ngx-lil-gui>
acts as a group of other <ngx-lil-gui>
<ng-container #anchor />
<span #spanElement>This is a span</span>
<ngx-lil-gui>
<!-- config object contains a dynamic HTMLElement that we can control -->
<ngx-lil-gui [config]="config" />
<ngx-lil-gui title="SPAN" [object]="spanElement.style" />
</ngx-lil-gui>
However, there’s nothing to stop the consumers to use both [config]
and [object]
on <ngx-lil-gui>
<ngx-lil-gui [config]="config" [object]="object" />
To apply this constraint, we can modify our selector as follow:
@Component({
selector: `
ngx-lil-gui:not([config]):not([object]),
ngx-lil-gui[config]:not([object]),
ngx-lil-gui[object]:not([config])
`,
/* ... */
})
export class NgxLilGui implements OnInit, OnDestroy {
/* ... */
}
Now, the consumers can instantiate NgxLilGui
component by using <ngx-lil-gui />
, <ngx-lil-gui [config] />
, or <ngx-lil-gui [object] />
but never <ngx-lil-gui [config] [object] />