Я заметил, что кнопка дизайн-системы Clarity не содержит элемента-обертки в DOM. Мне это нравится по разным причинам (ясность – без каламбура, доступность).
Я искал решения, позволяющие сделать такую вещь. Некоторые решения рискуют повлиять на обнаружение изменений Angulars и другие механизмы.
Решение, выбранное Clarity, кажется очень чистым. Но я не могу заставить его работать: лучший результат, который мне удалось, - это по-прежнему получить элемент-оболочку и содержимое, помещенное как родственный элемент в DOM.
Вот код Clarity для кнопки: https://github.com/vmware-clarity/ng-clarity/blob/main/projects/angular/src/button/button-group/button.ts И вот как это отображается:
Насколько я понимаю, как они это сделали:
@Component({
selector: 'clr-button',
template: `
<ng-template #buttonProjectedRef>
<button
export class ClrButton implements LoadingListener {
@Output('click') _click = new EventEmitter<boolean>(false);
@ViewChild('buttonProjectedRef', { static: true }) templateRef: TemplateRef<ClrButton>;
Как ни странно, я не вижу, где используется имя свойства viewchild («templateRef»).
На самом деле у компонента кнопки есть собственный селектор clr-button
, но он не будет работать сам по себе, для него требуется родительский компонент clr-button-group
.
В демо-версиях они это используют вот так
<clr-button-group>
<clr-button>1</clr-button>
<clr-button>2</clr-button>
<clr-button>3</clr-button>
<clr-button [clrInMenu] = "true">4</clr-button>
<clr-button [clrInMenu] = "true">5</clr-button>
<clr-button [clrInMenu] = "true">6</clr-button>
</clr-button-group>
Итак, кнопки существуют внутри Content Children
Таким образом, группы кнопок сначала принимают дочерний контент всех кнопок.
export class ClrButtonGroup implements AfterContentInit, AfterViewInit {
@Input('clrToggleButtonAriaLabel') clrToggleButtonAriaLabel: string = this.commonStrings.keys.rowActions;
@ViewChild('menuToggle') menuToggle: ElementRef<HTMLElement>;
@ViewChild('menu') menu: ElementRef<HTMLElement>;
@ContentChildren(ClrButton) buttons: QueryList<ClrButton>; // this line here!
После этой обработки происходит нажатие кнопок на menuButtons
, затем, наконец, над кнопками выполняется цикл и визуализируется с использованием ng-template
.
<ng-template *ngFor = "let menuButton of menuButtons" [ngTemplateOutlet] = "menuButton.templateRef"></ng-template>
Но ведь им все же удается отображать только тег <button>
для кнопок, которые не входят в группу? Может быть, я связался с неправильным файлом ts в Clarity? Я думал, что это «автономная» кнопка.
@KoertvanKleef, пожалуйста, поделитесь примером, где это происходит, на github.
В их историях из сборника рассказов есть примеры, где кнопка используется в качестве кнопки ClrButton: github.com/vmware-clarity/ng-clarity/blob/main/.storybook/… . В этих историях селектор выглядит просто как тег button
. В button-group/button.ts ( github.com/vmware-clarity/ng-clarity/blob/main/projects/angular/…) указан селектор тегов clr-button
, но они тоже просто отображаются <button>
в DOM.
@KoertvanKleef Они делают то же самое: определяют кнопку, добавляют ссылку #buttonRef
, затем используют ее для рендеринга внутри ng-template
они идут долгим путем: если им не нужен селектор, им следует просто определить компонент с помощью селектора класса .cls-button
или селектор атрибутов [clsButton]
это более простой способ добиться того, чего вы хотите!
Я не совсем уверен, что понимаю. Если компонент button-group/button.ts (с селектором clr-button
) используется в историях кнопок, то как angular узнает, что эти <button>
на самом деле являются clr-button
? Поскольку button
не соответствует селектору кнопки clr.
@KoertvanKleef Итак, это не та кнопка, о которой вы говорите, это просто обычные кнопки, они clr-button
не могут существовать без собственного селектора <clr-button/>
Я думаю, что понял. Таким образом, кнопки, являющиеся частью группы кнопок, могут отображаться как button
, поскольку группа кнопок отображает их содержимое (таким образом, опуская оболочку), а отдельные кнопки представляют собой просто кнопки HTML с CSS?
@KoertvanKleef Да, именно, попробуйте мое предложение для разных селекторов компонентов, они тоже не создают ненужных элементов!
Вероятно, они использовали рендерер для замены имени тега хоста, и если да, то это не лучшая идея. Вы можете использовать компонент в качестве селектора атрибутов на кнопке, как это делает Angular Material, и это лучшая идея, потому что при замене тега хоста элемент не уничтожается автоматически Angular, и вам придется позаботиться об этом самостоятельно. Также структурные директивы, такие как
*ngIf
, могут нарушаться.