Недавно мне пришлось реализовать представление popover со многими вариантами, основанными на сложных условиях. Использование ngSwitch
в этом случае было невозможно, а использование ngIf
нечитабельно и многословно.
Вот как я решил подойти к этой проблеме. Первым шагом было создание директивы с именем TemplateIdDirective
:
@Directive({ selector: 'ng-template[id]', standalone: true }) export class TemplateIdDirective { @Input() id: string; tpl = inject(TemplateRef); }
Директива нацелена на шаблоны с вводом id
. Затем я создал варианты в шаблоне компонента и присвоил каждому id
:
<-- trace-information.component.html --> <div> <p>{{ header }}</p> <ng-template [ngTemplateOutlet]="body"></ng-template> </div> <ng-template id="variation-one">...</ng-template> <ng-template id="variation-two">...</ng-template> <ng-template id="variation-three">...</ng-template> <ng-template id="variation-four">...</ng-template> <ng-template id="variation-five">...</ng-template>
Наконец, я написал всю логику в компоненте, получил ссылку на шаблоны и отрендерил тот, который совпал:
@Component({ selector: 'app-trace-information', standalone: true, imports: [TemplateIdDirective], templateUrl: './trace-information.component.html' }) export class TraceInformationComponent { header = ''; @Input() traceInfo: TraceInfo; @ViewChildren(TemplateIdDirective) templates: QueryList<TemplateIdDirective>; private cdr = inject(ChangeDetectorRef); ngAfterViewInit() { this.resolveView(); } private resolveView() { // All the complex conditions are defined here. // In real life is way more complicated than that. // This is only for illustration if(...) { this.header = '...'; this.body = this.getTemplate('variation-one'); } else if(...) { if(...) { this.header = '...'; this.body = this.getTemplate('variation-two'); } else { this.header = '...'; this.body = this.getTemplate('variation-three'); } } this.cdr.detectChanges(); } private getTemplate(id: string) { return this.templates.find((tpl) => tpl.id === id).tpl; } }
Создание компонента для каждого варианта привело бы к тому же результату, но в этом случае представление крошечное, поэтому создание компонента для каждого варианта было бы излишним.
Подпишитесь на меня в Medium или Twitter, чтобы узнать больше об Angular и JS!