【问题标题】:Angular2 NgStyle not updating on clickAngular2 NgStyle 没有在点击时更新
【发布时间】:2021-06-20 14:16:59
【问题描述】:

组件有一个来自其父级的输入,并且有一个针对该输入对象的输出事件。 NgStyle 从组件中获取样式对象进行样式设置。点击事件改变了布尔值,但样式对象没有相应更新,因此颜色保持不变。我必须重新分配一个新对象才能让 NgStyle 看到新的布尔值。我做错了什么?

ProductItemComponent.ts:

import { Component, OnInit, Input, Output, EventEmitter } from '@angular/core';
import {Product} from '../../model/product';

@Component({
selector: 'app-product-item',
templateUrl: './product-item.component.html',
styleUrls: ['./product-item.component.css']
})

export class ProductItemComponent implements OnInit {

  @Input() public product!:Product;
  @Output() private updateStatus: EventEmitter<Product>;

  public statusTextStyle:object;
  public classStyle:object;

  constructor() {
    this.updateStatus = new EventEmitter<Product>();
  }


 ngOnInit(): void {

    this.statusTextStyle = {
       // if true color green, if false red
      "color" : this.product.getStatus() ? "var(--ok)" : "var(--danger)"
    }

 }

  onUpdateStatus(event){
    this.updateStatus.emit(this.product);

    // have to reassign a new object to change style
    this.statusTextStyle = {
      "color" : this.product.getStatus() ? "var(--ok)" : "var(--danger)"
    }

    console.log(this.statusTextStyle);
  }

}

产品-item.component.html:

<div class="productContainer">
  <div class="overlay">
      <div [ngStyle]="statusTextStyle">{{product.name}}</div>
      <hr>
      <div>Status: {{product.getStatus()}}</div>
      <div>Price: {{product.price}}</div>
      <br>
      <div>Code: {{product.code}}</div>
      <br>
      <div>Stock: {{product.quantity}}</div>
      <hr>
      <button (click)="onUpdateStatus($event)">UPDATE STATUS</button>
  </div>
</div>

家长:

import { Component, OnInit } from '@angular/core';
import { Product as ProductModel} from '../../model/product';

@Component({
   selector: 'app-product-list',
   templateUrl: './product-list.component.html',
   styleUrls: ['./product-list.component.css']
 })

  export class ProductListComponent implements OnInit {

  products: Array<ProductModel>;

  constructor() { }

   ngOnInit(): void {
     this.products = [
       new ProductModel('A','1',3,40),
       new ProductModel('B','2',4,50),
       new ProductModel('C','3',22,41),
       new ProductModel('E','4',342,433),
       new ProductModel('Z','5',33,477)
     ]
   }

   onUpdateStatus(product:ProductModel){

     product.setStatus(!product.getStatus());
     console.log(product.getStatus());

   }

 }

父 html:

<div class="productList">
<div *ngFor="let product of products; let index as i;">

    <app-product-item [product]="product" (updateStatus)="onUpdateStatus($event)"></app-product-item>
    
</div>

产品型号:

  export class Product {

  private _status:boolean = false;

  constructor(public name:string,
              public code:string,
              public price:number,
              public quantity:number){}

  public getStatus():boolean{
      return this._status;
  }

  public setStatus(status:boolean):void{
      this._status = status;
    }
  }

如果this.statusTextStyle 没有重新分配一个新对象(回想一下getStatus()),NgStyle 使用在ngOnInit 中设置的样式

Stackblitz demo

【问题讨论】:

  • 您能提供您的ngStyle 代码吗?我猜你的问题是你应该分配this.statusTextStyle.color = this.product.getStatus() ? "var(--ok)" : "var(--danger)"。然后你可能需要调用ChangeDetectorRef(注入)changeDetectorRef.detectChanges()。由于性能原因,我不推荐这种方法,如果您可以提供更多代码,也许我可以考虑别的。 :)
  • 为什么你期望product.getStatus() 在这段代码中似乎没有改变产品对象的任何东西时返回不同的东西?您似乎还缺少基于该错误消息的CommonModule 导入?在询问有关 ngStyle 用法的问题时,您的 ngStyle 绑定也会很有用。
  • @JorgeMussato 我将this.statusTextStyle 初始化为ngOnInit 中的一个新对象。如果我像this.statusTextStyle.color 一样分配错误投诉:“对象”类型上不存在属性颜色。
  • @bryan60 我最近刚接触到 Angular,我跟着书 Angular Up and Running。如果我理解正确,组件中的event emitter 将触发其父级的此输出事件。正如我在 console.log 中显示的那样,该值确实发生了变化
  • 你可以创建一个最小的 stackblitz 演示

标签: angular typescript


【解决方案1】:

兄弟,我想在这里添加我的一段代码,它运行得很好,也许它会对你有所帮助。

 Style1={
     fontSize: '3em',
     backgroundColor: this.CardData > 1 || this._ProductQuantity > 1 ? 'ivory' : "orange",
     color: this.CardData > 1 || this._ProductQuantity > 1 ? "green" : "red",
     'fa': true,
     'far fa-check-square': this.CardData > 1 || this._ProductQuantity > 1, 
     'far fa-times-circle': this.CardData < 1 || this._ProductQuantity < 1

   };

我没有使用“var(--ok)”,而是使用颜色的直接值。 如果对你有帮助,请勾选我的回答

【讨论】:

  • 哦。条件可能有问题。还有其他帮助吗?
【解决方案2】:

@CloudWave,你需要初始化输出:@Output() private updateStatus: EventEmitter&lt;Product&gt;=new EventEmitter&lt;Product&gt;();

但是,如果您检查您的代码,请注意不要在 ngOnInit 其他任何地方更改 statusTextStyle。 ngOnInit 仅在第一次绘制组件时发生(或者如果您在 *ngFor 下有一个组件并且还更改了 *ngIf 下的数组)。

如果您取消注释 //reassign object only works 下的行,您可以检查该工作。

另一种方法是做一个吸气剂

get statusTextStyle(){
    return {
      color: this.product.getStatus() ? "var(--ok)" : "var(--danger)"
    };
  }

你的forked stackblitz using a getter

注意:当您将对象传递给 Input 时,您无需将产品传递给 @Output,对象中的任何更改 - 在子级或父级中 - 都会更改 apaarence

更新好吧,说明不清楚。我想说的是,当您将 @Input 与对象一起使用时,对象总是相同的。您可以在任何地方更改对象的一个​​属性-在父级或子级中-因此,我们可以在子级中进行

  onUpdateStatus(event) {
    this.product.setStatus(!this.product.getStatus());
  }

我们不需要更改父级中的“产品”,也不需要使用@Output。

【讨论】:

  • 我想如果我在 ngOnInit 中初始化样式,之后样式会不断变化。所以 getter 用在 &lt;div [ngStyle]="statusTextStyle"&gt;{{product.name}}&lt;/div&gt; 行中? pass to the @Output the product 是什么意思?
  • “ngOnInit”不创建变量之间的关系,获取实际变量并计算其他变量。关于@Input,我更新了答案,清晰的注释了。
  • 感谢您的回答。我其实是在做运动。书上说为了让子组件真正可重用,数据对象应该由其父组件传入,这就是为什么我使用@Output装饰器来提供封装。
猜你喜欢
  • 1970-01-01
  • 2019-12-09
  • 2016-04-04
  • 1970-01-01
  • 2022-01-24
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多