Angular изменить стиль дочернего компонента от родительского компонента, но не глобально - PullRequest
0 голосов
/ 17 марта 2020

Я создал общий компонент (<nextgen-table></nextgen-table>) на основе Mat-table (Angular Материал). Используя этот компонент внутри проекта, обнаружите, что мне нужно изменить поведение (ширину) столбцов таблицы.

Я экспортировал nextgen-table в другие мои компоненты (скажем, X, Y), где nextgen-table, конечно, дочерний компонент.

Чтобы изменить ширину заданных c столбцов таблицы mat, я должен использовать что-то вроде этого:

mat-cell:nth-child(1),
mat-header-cell:nth-child(1) {
    flex: 0 0 40%;
    text-align: left;
} 
mat-cell:nth-child(2),
mat-header-cell:nth-child(2) {
    flex: 0 0 20%;
}

Приведенный выше код CSS, который я реализовывал в X Компонент * в Компонентном декораторе x.component.ts. После этого решения я переходил от компонента X к компоненту Y, в котором я не реализовал вышеуказанный код CSS. Но у компонента Y были первые два столбца, как я хотел только для компонента X, но каким-то образом у компонента Y также было то, чего я не хотел для компонента Y.

Поэтому мой вопрос состоит в том, как я могу обновить стиль nextgen-table от родительского компонента, который применяется только для родительского компонента, но не для других компонентов.

Я также пытался использовать

:host(mat-cell:nth-child(1)){
  flex: 0 0 40%;
  text-align: left;
}

:host(mat-header-cell:nth-child(1)) {
    flex: 0 0 40%;
    text-align: left;
}

, но ничего не произошло / не изменилось.

Заранее спасибо за помощь

Ответы [ 2 ]

1 голос
/ 21 марта 2020

Все, что вам нужно сделать - это использовать селекторы псевдокласса :host и ::ng-deep в вашем компоненте X или Y.

Вот рабочая демонстрация .

А вот краткое объяснение.

Стили, которые написаны для <nextgen-table> внутри, скажем, nextgen-table.component.css, инкапсулируются angular путем добавления определенных c атрибутов для каждого стиля. т. е. если вы написали что-то вроде

.mat-header-cell{
    background-color: #ff0000;
}

, тогда оно станет примерно таким:

.mat-header-cell[_ngcontent-c29]
    background-color: #ff0000;
}

Так что все, что нам нужно сделать, это переопределить этот стиль внутри нашего компонента X или компонента Y .

У нас есть ::ng-deep псевдоселектор, который не позволит angular инкапсулировать компоненты css.

Но использование ::ng-deep приведет к утечке нашего css в родительские компоненты также. Таким образом, чтобы предотвратить это, нам нужно инкапсулировать стиль ::ng-deep. для этого мы можем использовать :host псевдоселектор.

, поэтому, если мы напишем следующее css внутри компонента X,

:host ::ng-deep .x-table .mat-header-cell{
  background-color: lightblue;
}

, тогда оно станет примерно таким,

[_nghost-c82] .x-table .mat-header-cell {
    background-color: lightblue;
}

теперь этот выбор css имеет более высокий приоритет, чем стиль, записанный в компоненте таблицы .mat-header-cell[_ngcontent-c29].

Вот так мы можем переопределить стиль дочернего компонента внутри любого родительского компонента. Я надеюсь, что это поможет.

Обновление: Как вы можете видеть в официальных документах Angular , что ::ng-deep устарело.

Пронзающий теневой комбинатор не рекомендуется, и поддержка удаляется из основных браузеров и инструментов. Таким образом, мы планируем отказаться от поддержки в Angular (для всех 3 of / deep /, >>> и :: ng-deep). До тех пор :: ng-deep следует предпочитать для более широкой совместимости с инструментами.

Поэтому, если вы не хотите зависеть от ::ng-deep than,

You можете использовать ViewEncapsulation.None в компоненте таблицы <nextgen-table>, который вы уже пробовали. Демонстрация здесь

И чтобы предотвратить утечку стиля в другие компоненты, вы можете ограничить стиль таблицы, добавив селектор перед всеми стилями, подобными этим.

nextgen-table .mat-header-cell{
    background-color: #ff0000;
}

и затем вы делаете то же самое для своего компонента X.

  • Отключить инкапсуляцию представления с помощью ViewEncapsulation.None
  • Затем переопределить стили для компонента таблицы, написав стили, которые имеют более высокую специфичность, чем фактический стиль таблицы.

отключите инкапсуляцию в стороне вашего компонента X,

@Component({
  selector: "app-x",
  styleUrls: ["x.component.css"],
  templateUrl: "x.component.html",
  encapsulation: ViewEncapsulation.None
})
export class XComponent {

}

, а затем переопределите стиль компонента таблицы в x.compoent.css

app-x nextgen-table .mat-header-cell{
  background-color: lightblue;
}

Если вы не хотите отключать инкапсуляцию представления, тогда вы можете записывать стили непосредственно в глобальную таблицу стилей styles.css.

Просто помните, что все дело в переопределении и ограничении ваших стилей.

1 голос
/ 20 марта 2020

Вы можете использовать псевдокласс *1003*, чтобы специально нацеливать дочерние элементы без изменения инкапсуляции представления для всего компонента (что будет означать утечку всех его правил).

Примечание : ::ng-deep помечено как устаревшее для нескольких основных версий, но они не будут удалять Suppoprt, пока не найдут обходной путь.

parentX. html

<div class="compContainer">
    <nextgen-table></nextgen-table>
</div>

parentX.s css

::ng-deep .compContainer nextgen-table
{
    mat-cell:nth-child(1),
    mat-header-cell:nth-child(1) {
        flex: 0 0 40%;
        text-align: left;
    } 
    mat-cell:nth-child(2),
    mat-header-cell:nth-child(2) {
        flex: 0 0 20%;
    }
}

Вы также можете добавить свои css правила к глобальный style.scss файл.

//Rules for parent X
app-parent-componentX .compContainer nextgen-table
{
    mat-cell...
}

//Rules for a parent Y
app-parent-componentY .compContainer nextgen-table
{
    mat-cell...
}
...