Angular-如何在使用ViewEncapsulation.Native时访问html元素

时间:2019-05-16 20:47:43

标签: javascript html angular typescript shadow-dom

我遇到的问题是,尝试通过ID访问html元素时出现以下错误。当用户单击按钮以将其他样式类应用于元素时,我尝试访问classList。通常,除非我将viewEncapsulation切换回默认的仿真设置,否则类列表和元素通常始终为null。

错误消息

TypeError: Cannot read property 'classList' of null

问题: 我正在尝试让该特定组件不继承我已通过angular.json文件导入到项目中的第三方SCSS文件。当我使用默认的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 个答案:

答案 0 :(得分:1)

我想到的访问HTML元素的最简单方法是使用Angulars ElementRef。您可以阅读有关该here的更多信息。 请谨慎使用!下面是一个在您的情况下如何使用它的示例:

在您的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;
}

希望对您有帮助!

答案 1 :(得分:1)

我认为您在问两个不同的问题:

1。如何在Angular中动态添加和删除类:

在Angular中,您应尝试避免直接使用文档。一种基于条件添加类的好方法是使用ngClass指令,您可以在此处了解更多信息:https://angular.io/guide/template-syntax#ngclass

动态添加类的另一种方法是使用ViewChild从模板中获取元素,然后使用有角度的Renderer在元素上设置类(如果您用Google搜索,则会找到更多信息)

2。如何让我的组件不从Angular.json文件继承全局CSS

我想不出解决方案。使用诸如ViewEncapsulation.None和ViewEncapsulation.Emulated之类的封装策略将无法解​​决此问题,因为它们只会影响此组件中的类,而不会扩展到其他组件。它不会影响进入此组件的全局类。