在组件中使用对象时,ngClass 不切换值

ngClass does not switch value when using object in component

提问人:Bagira 提问时间:11/15/2023 最后编辑:Bagira 更新时间:11/16/2023 访问量:70

问:

当我使用以下代码切换类时,一切正常

<p [ngClass]="idPresent ? 'alert alert-success' : 'alert alert-danger'">
  Working
</p>

在更改组件中的值时,我可以看到正在应用的相应类,IdPresent

但是当我出于相同目的使用组件中的对象时,它仅在 is 时才有效。当我将 设置为 时,以下代码不会应用相应的类。idPresentfalseidPresenttrue

<p [ngClass]="idValueClass">
   Not working
</p>
public idPresent = false;
 
public idValueClass = {
  "alert alert-success" : this.idPresent,
  "alert alert-danger"  : !this.idPresent
};

有人能帮我弄清楚我做错了什么吗?

更新:

在收到来自 REST API 调用的响应后,我正在更改 idPresent 的值

 ngOnInit(): void {
 this.http.get('http://localhost:8083/v1/uniqueid', {
  headers: {'Authorization':'Basic dXNlcjpwYXNzd29yZA=='}
 })
 .subscribe(response => {
    if(response) {
      console.log(response)
       this.serverId = response;
       this.idPresent = true;
    } else {
       this.idPresent = false;
    }
    console.log("idPresent : " + this.idPresent)
 })

}

收到服务器的响应后,我可以在控制台中看到更新的值。

CSS Angular angular-ng-class

评论

0赞 Eliseo 11/16/2023
如果你没有使用信号,请记住在订阅函数不仅给这个.idPresent elseidValueClass

答:

1赞 Yong Shun 11/15/2023 #1

我相信您提到了删除“警报”类的问题。

文档中,

对象 - 键是 CSS 类,当值中给出的表达式计算结果为真实值时,会添加这些类,否则它们将被删除。

这导致最后一个“警报”已经并将从类中删除。false

修改如下:idValueClass

public idValueClass = {
  alert: true,
  'alert-success': this.idPresent,
  'alert-danger': !this.idPresent,
};

演示@ StackBlitz


更新

正如 @Eliseo 所提出的,如果您有按钮或逻辑来更新 ,则不会自动反映最新值。idPresentidValueClass

您需要一个触发/更改事件来覆盖 .idValueClass

<button class="btn btn-primary" (click)="onClick()">Update</button>
onClick() {
  this.idPresent = !this.idPresent;
  this.idValueClass = {
    alert: true,
    'alert-success': this.idPresent,
    'alert-danger': !this.idPresent,
  };
}

或者实现一个 getter(但是这不是一个好的做法,参考:模板中的 getter 和 setter 是一个坏主意idValueClass)

评论

1赞 Eliseo 11/15/2023
请参阅更改“this.idPresent”时“idValueClass”对象不会更改
0赞 Yong Shun 11/15/2023
嗨,@Eliseo,敏锐的眼睛!这将是另一个问题,因为 的更改不会更新。除非您需要覆盖更新时间。idPresentidValueClassidValueClassidPresent
1赞 Eliseo 11/15/2023
从 Angular 16 开始,我们也可以使用信号。注意:就我个人而言,我不太喜欢,但我觉得我们需要习惯才能使用
0赞 Bagira 11/16/2023
@YongShun我更新了问题以显示我如何更新值。你看到那里有什么问题吗?
1赞 Yong Shun 11/16/2023
嗨,@Bagira,您提到的更新不会反映到 .与我为更新部分编写的内容类似。当您首先声明变量并使用 as 值而不是引用类型初始化值时。这不会自动更新 .您需要覆盖/重新分配信号,或者将信号用作@Eliseo的答案。idPresentidValueClassidValueClassidPresentidValueClassidValueClass
0赞 Anjasmara Dwi.S 11/15/2023 #2

我以前遇到过这个问题,我曾经遇到过任何键名类,例如“成功”、“警报”、“警告”等,之前的情况相同。我尝试将其设置为单个名称类(alert-success),而不是多个类(“alert alert-success”)。

您可以尝试以下代码 =

enter code here

public idValueClass = {
  'alert': true,
  'alert-success': this.idPresent,
  'alert-danger': !this.idPresent,
};

我在 ngClass 上使用 tenary 的更多建议条件,然后在 .ts 上获取值

idValueClass() {
  return this.idValueClass ? 'alert alert-success' : 'alert alert-danger'
};
2赞 Eliseo 11/15/2023 #3

为了补充@Yong顺,在 Angular 16 和 17 中,我们可以使用信号

我们可以定义:

  public idPresent = signal(false);

  public idValueClass = computed(() => ({
    alert: true,
    'alert-success': this.idPresent(),
    'alert-danger': !this.idPresent(),
  }));

  onClick() {
    this.idPresent.update(value => !value);
  }

要小心,我们需要重新替换的.htmlidPresentidPresent()idValueClassidValueClass()

  <p [ngClass]="idValueClass()">
    Not working
  </p>
  Current idPresent: {{ idPresent() }}

从永顺 stackblitz 中完全偷来的堆栈闪电战

注意:在我使用的 stackblitz 中看到了这一点,但是,当信号更新时,Angular 会更新整个视图changeDetection:ChangeDetectionStrategy.OnPush

评论

0赞 Bagira 11/17/2023
我尝试使用信号,但是在html中进行建议的更改以将idValueClass替换为idValueClass()时,出现以下错误:错误TS2349:此表达式不可调用。键入 '{ alert: boolean;“警报成功”: WritableSignal<boolean>;“alert-danger”:布尔值;}' 没有呼叫签名。
1赞 Eliseo 11/17/2023
@Bagira,检查我答案中的堆栈闪电战,您需要定义:idValueClass = computed(() => ({...})