Angular - Как получить доступ к элементу html при использовании ViewEncapsulation.Native - PullRequest
0 голосов
/ 16 мая 2019

У меня проблема с тем, что я получаю следующую ошибку при попытке доступа к элементу html по идентификатору. Я пытаюсь получить доступ к classList, когда пользователь нажимает кнопку, чтобы применить другой элемент стиля к элементу. Список классов и элемент в целом всегда равны нулю, если только я не переключаю viewEncapsulation обратно на настройку эмуляции по умолчанию.

Сообщение об ошибке :

TypeError: Cannot read property 'classList' of null

Проблема : Я пытаюсь, чтобы этот конкретный компонент не наследовал сторонний файл SCSS, который я импортировал в проект через файл angular.json. Когда я использую ViewEncapsulation.Emulated по умолчанию, компонент наследует глобальные стили SCSS, что противоречит стилю некоторых компонентов.

Файловая структура нормальная, я помещаю SCSS и HTML в соответствующие файлы, затем импортирую их в компонент.

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

Компонент .ts:

import { Component, ViewEncapsulation, OnInit } from '@angular/core';

@Component({
  encapsulation: ViewEncapsulation.Native,
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.scss']
})
export class AppComponent implements OnInit {
  title = 'scssTesting';

  constructor() { }

  step: string = 'step1';

  step1: any;
  step2: any;
  step3: any;


  ngOnInit() {

  }

  next() {

    this.step1 = document.getElementById('step1');
    this.step2 = document.getElementById('step2');
    this.step3 = document.getElementById('step3');


    if (this.step === 'step1') {
      this.step = 'step2';
      this.step1.classList.remove("is-active");
      this.step1.classList.add("is-complete");
      this.step2.classList.add("is-active");

    } else if (this.step === 'step2') {
        ....
  }
}

Компонент .scss

.progress {
  position: relative;
  display: flex;
  .........
}

Компонент .html

<div class="container">
    <div class="progress">
        <div class="progress-track"></div>
        <div id="step1" class="progress-step">
            Step One
        </div>
        <div id="step2" class="progress-step">
            Step Two
        </div>
        <div id="step3" class="progress-step">
            Step Three
        </div>
    </div>
    <button (click)="next()">Next Step</button>
</div>

Ответы [ 2 ]

1 голос
/ 17 мая 2019

Я думаю, что вы задаете два разных вопроса:

1.Как динамически добавлять и удалять классы в Angular:

В Angular вы должны стараться избегать прямого использования документа.Хороший способ добавления класса, основанного на условии, - это директива ngClass. Подробнее об этом можно прочитать здесь: https://angular.io/guide/template-syntax#ngclass

Другой способ динамического добавления класса заключается в получении элемента из шаблона с помощью ViewChild.а затем установить класс для элемента с помощью углового рендерера (вы найдете больше информации, если вы его гуглите)

2.Как сделать так, чтобы мой компонент не наследовал глобальный CSS из файла Angular.json

Я не могу придумать решение для этого.Использование стратегий инкапсуляции, таких как ViewEncapsulation.None и ViewEncapsulation.Emulated, не решит эту проблему, поскольку они влияют только на классы в этом компоненте, не распространяясь на другие компоненты.Он не влияет на глобальные классы, входящие в этот компонент.

1 голос
/ 17 мая 2019

Самый простой способ получить доступ к элементу HTML - использовать Angulars ElementRef. Вы можете прочитать больше об этом здесь . Пожалуйста, используйте это с осторожностью! Ниже приведен пример того, как использовать его в вашем случае:

В вашем app.component.html

<div #myelement>This is Pink</div>

В вашем app.component.ts

import { Component, ViewChild, ElementRef, AfterViewInit } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements AfterViewInit {
  @ViewChild('myelement') el: ElementRef;

  ngAfterViewInit() {
    this.el.nativeElement.classList.add("myclass");
  }
}

В вашем app.component.css

.myclass {
    color: pink;
    font-weight: bold;
}

РЕДАКТИРОВАТЬ:

Для чистого стиля, как уже упоминалось @SnorreDan, было бы лучше использовать директиву Angulars [ngClass]. Вы можете посмотреть, как это сделать, в следующем примере:

В вашем app.component.html

<div [ngClass]="myColorClass">This may change color!</div>

<button (click)="makePink()">Pink</button>
<button (click)="makeGreen()">Green</button>

В вашем app.component.ts

import { Component } from '@angular/core';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  myColorClass: string

  makePink() {
    this.myColorClass = 'pink';
  }

  makeGreen() {
    this.myColorClass = 'green';
  }
}

В вашем app.component.css

.pink {
    color: pink;
    font-weight: bold;
}

.green {
    color: green;
    font-weight: bold;
}

Надеюсь, это поможет!

...