angular - лучшая практика использования условно разных макетов в компоненте

Предположим, у нас есть несколько компонентов, каждый из которых должен иметь разные макеты/пользовательский интерфейс (шаблоны), обусловленные размерами экрана.

Мое решение состоит в том, чтобы создать такой компонент:

import {Component} from '@angular/core';
import {BreakpointObserver, Breakpoints} from '@angular/cdk/layout';

@Component({
    selector: 'ui-switcher',
    template: `
        <ng-content *ngIf="isSmall" select="mobile"></ng-content>
        <ng-content *ngIf="!isSmall" select="web"></ng-content>
`
})
export class UiSwitcherComponent {
    public isSmall: boolean;

    constructor(breakpointObserver: BreakpointObserver) {
        breakpointObserver.observe([Breakpoints.Small, Breakpoints.XSmall]).subscribe(result => {
            this.isSmall = result.matches;
        });
    }

}

и используйте его таким образом:

<ui-switcher>
    <web>
        <!-- a ui suited for large screens -->
    </web>

    <mobile>
        <!-- a very different ui suited for small mobile screen displays-->

    </mobile>
</ui-switcher>

Это решение может иметь некоторые подводные камни. Например, мы не можем использовать одни и те же ссылки на шаблоны в разделах <mobile> и <web>. (выше мы использовали #searchInput и #searchInput2).


Каковы рекомендации для таких ситуаций?


person Fartab    schedule 29.04.2018    source источник


Ответы (1)


В вашем примере вы просто добавляете класс CSS, если isSmall равно false. Вы можете решить эту проблему, просто имея 1 вход (а не 2) и условно добавив класс.

Итак, вместо условного рендеринга 2 идентичных блоков HTML... Вы рендерите 1 блок с условным классом CSS.

Пример ниже:

@Component({
    selector: 'ui-switcher',
    template: `
        <input class="form-control" [ngClass]="{'mr-2': !isSmall}"> 
        type="text" (keyup)="this.search(searchInput.value)">
`
})

Теперь, если ваш контент действительно изменится, и вам нужно больше, чем просто *ngIf... Тогда хорошим решением будет использование в шаблоне if...else или даже if...elseif...else.

Ссылка здесь: Как использовать *ngIf else в Angular?

Подробнее об использовании условного класса см. в этом сообщении: Angular: условный класс с *ngClass

Надеюсь, это помогло! ;)

Обновление:

ОП имел в виду изменение, которое затронуло только класс CSS, но если вы хотите динамически загружать компонент в блок кода... Я бы сказал, что вы используете ngComponentOutlet.

Пример:

        <fieldset *ngFor="let component of components">
            <ng-container *ngComponentOutlet="component.name;
                                ngModuleFactory: dynamicComponentsModule;"></ng-container>
        </fieldset>

Преимущество этого подхода в том, что вы можете создать карту, и для каждой опции у вас есть связанный с ней Component. Пример:

map = [
   'option1': ComponentForOption1,
   'option2': ComponentForOption2
];

Я бы предложил этот пост, который содержит более полный пример:

Динамический шаблон на основе значения, а не переменной с ngTemplateOutlet

При этом в этом ответе я предоставил информацию о том, как иметь:

  1. Динамические классы CSS
  2. Условный HTML со встроенным шаблоном if...elseif...else
  3. Динамическая загрузка компонентов
person SrAxi    schedule 29.04.2018
comment
Нет, изменения — это больше, чем просто класс css. Предположим, у нас есть много изменений в макете, что рассматривать их во всех компонентах громоздко. Нам нравится обрабатывать это в одном компоненте. - person Fartab; 30.04.2018
comment
@Фартаб Эй! Я обновил свой ответ объяснением того, как динамически загружать компонент. Если что-то не ясно, дайте мне знать. Ваше здоровье! :D - person SrAxi; 30.04.2018