Как мне условно обернутьмногократно? - PullRequest
0 голосов
/ 31 января 2019

Я попытался написать компонент-обертку, которому можно передать некоторый текст и некоторые параметры, которые затем отформатировали бы мой текст с помощью начальной загрузки, основываясь на этих параметрах.

Я пробовал это:

header-line.component.ts

@Component({
  selector:'header-line',
  templateUrl: 'header-line.component.html'
})
export class HeaderLineComponent {
  @Input level: number;
  // other inputs used for formatting skipped here
}

header-line.component.html

<div class="row">
  <div class="col-sm-12"> <!-- would really be [className]="..." based on skipped inputs -->
    <header-wrapper [level]="level">
      <!-- display of icon, based on skipped inputs -->
      <ng-content></ng-content>
    </header-wrapper>
  </div>
</div>

header-wrapper.component.ts

@Component({
  selector: 'header-wrapper',
  templateUrl: './header-wrapper.component.html'
})
export class HeaderWrapperComponent {
  @Input() level: number;
}

header-wrapper.component.html

<h1 *ngIf="level === 1"><ng-content></ng-content></h1>
<h2 *ngIf="level === 2"><ng-content></ng-content></h2>
<h3 *ngIf="level === 3"><ng-content></ng-content></h3>
<h4 *ngIf="level === 4"><ng-content></ng-content></h4>
<h5 *ngIf="level === 5"><ng-content></ng-content></h5>
<span *ngIf="!level || level < 1 || level > 5"><ng-content></ng-content></span>

Использование по назначению

Использование будет выглядеть примерно так:

<header-line [level]="1" [...]="...">Just a test h1</header-line>
<header-line [level]="2" [...]="...">Just a test h2</header-line>
<header-line [level]="3" [...]="...">Just a test h3</header-line>
<header-line [...]="...">Just a test span</header-line>

Ожидаемый результат

Я бы тогда ожидал, что на выходе получится нечто, эквивалентное:

<div class="row">
  <div class="cols-sm-12">
    <h1>Just a test h1</h1>
  </div>
</div>
<div class="row">
  <div class="cols-sm-12">
    <h2>Just a test h2</h2>
  </div>
</div>
<div class="row">
  <div class="cols-sm-12">
    <h3>Just a test h3</h3>
  </div>
</div>
<div class="row">
  <div class="cols-sm-12">
    <span>Just a test span</span>
  </div>
</div>

Эффективный выход

Однако я получаю следующее:

<div class="row">
  <div class="cols-sm-12">
  </div>
</div>
<div class="row">
  <div class="cols-sm-12">
  </div>
</div>
<div class="row">
  <div class="cols-sm-12">
  </div>
</div>
<div class="row">
  <div class="cols-sm-12">
    <span>Just a test span</span>
  </div>
</div>

Анализ проблем

Мне понадобилось совсем немного времени, чтобы выяснить, что причиной моей проблемы является повторное использование в header-wrapper.component.ts, потому что оно, по-видимому, статично и не может быть использовано dynamically.

Следующие две ссылки объясняют, почему мои ожидания были разочарованы:

https://github.com/angular/angular/issues/9173

https://github.com/angular/angular/issues/8563

Поиск решения

Следующая ссылка на Stackoverflow показывает, как это можно сделать, если нужно поддерживать только два случая:

Как условно обернуть div вокруг ng-content

Используя этот подход, я справился со следующим:

Обновлено: header-wrapper.component.html

<h1 *ngIf="level && level === 1; else notOne">
  <ng-container *ngTemplateOutlet="content"></ng-container>
</h1>

<ng-template #notOne>
  <h2 *ngIf="level && level === 2; else notTwo">
    <ng-container *ngTemplateOutlet="content"></ng-container>
  </h2>
</ng-template>

<ng-template #notTwo>
  <h3 *ngIf="level && level === 3; else notThree">
    <ng-container *ngTemplateOutlet="content"></ng-container>
  </h3>
</ng-template>

<ng-template #notThree>
  <h4 *ngIf="level && level === 4; else notFour">
    <ng-container *ngTemplateOutlet="content"></ng-container>
  </h4>
</ng-template>

<ng-template #notFour>
  <h5 *ngIf="level && level === 5; else content">
    <ng-container *ngTemplateOutlet="content"></ng-container>
  </h5>
</ng-template>

<ng-template #content>
  <ng-content></ng-content>
</ng-template>

Это дает желаемый результат.

Мой вопрос

Это действительно единственный способ сделать это?Или есть более простой способ, которого мне не хватает?

1 Ответ

0 голосов
/ 31 января 2019

Основываясь на видео, связанном с Jota.Toledo, я предложил более компактную версию.

Обновлен header-wrapper.component.html

<h1 *ngIf="level && level === 1"><ng-container [ngTemplateOutlet]="content"></ng-container></h1>
<h2 *ngIf="level && level === 2"><ng-container [ngTemplateOutlet]="content"></ng-container></h2>
<h3 *ngIf="level && level === 3"><ng-container [ngTemplateOutlet]="content"></ng-container></h3>
<h4 *ngIf="level && level === 4"><ng-container [ngTemplateOutlet]="content"></ng-container></h4>
<h5 *ngIf="level && level === 5"><ng-container [ngTemplateOutlet]="content"></ng-container></h5>
<span *ngIf="!level || level < 1 || level > 5"><ng-container [ngTemplateOutlet]="content"></ng-container></span>

Это работает так же, как мое обновленное решение вопроса, но я нахожу эту версию более компактной и более удобочитаемой.

...