更好的 *ngIf 链接和“0”值检测?

Better *ngIf chaining and `0` value detection?

我们构建了一个类似仪表板的界面,并经常收到带有可选字段的通用对象,例如下面的 event 对象。 event 可能在加载模板时未定义,它可能有也可能没有 daysRemaining ?: number 参数;如果设置了,可能是0.

为了确保在上述场景中实际打印出 0 值,我们使用此模式:

<div *ngIf="event?.daysRemaining?.toString().length > 0">
  {{event.daysRemaining}} days
</div>

.toString() 是必需的,因为 属性 'length' 在类型 'number' 上不存在。

我们的对象树可以比上面的例子深。我们可以在 <ng-container>*ngIf 中包含共同的父树,但我们很少这样做。

必须有更优雅的方法来做到这一点,特别是关于需要在几乎每个可选 number.

上调用 .toString()

这似乎更有效率:

<div>
  {{event?.daysRemaining + ' days'}}
</div>

但缺点是如果我们需要选择性地向 <div> 添加内容(例如 color: reddaysRemaining < 0),我们仍然需要所有检查。

您可以使用方法检查组件中的条件。

<div *ngIf="daysRemaining(event)">
  {{event.daysRemaining}} days
</div>

打字稿方法将如

daysRemaining(event){
    if(event && event.daysRemaining.toString().length > 0){
        return true;
    } else {
        return false;
    }
}

在组件 class 中,我会使用类似的东西:

get daysRemaining(){
    return this.event && (this.event.daysRemaining || this.event.daysRemaining === 0) ?
             this.event.daysRemaining + ' days' : undefined;
}

并在模板中:

<div>
  {{daysRemaining}}
</div>

如果您认为自己可能经常这样做,您可以创建一个管道:

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({name: 'printIfDefined'})
export class PrintIfDefinedPipe implements PipeTransform {

    transform(value:number, suffix?:string): number {
      let suffix = (suffix ? ' ' + suffix : '');
      return (value || value === 0) ? value + suffix : undefined;
    }

}

并在模板中:

<div>
      {{event?.daysRemaining | printIfDefined: 'days' }} 
</div>

在这两种选择中,div 仍然在 de DOM 上注入,但由于它没有内容,因此不应影响您的应用程序(除非您具有固定宽度的 css 或类似的东西)。

如果 DOM space 占用困扰你,另一种选择可能是指令:

import { Directive, ElementRef, HostListener, Input } from '@angular/core';

@Directive({
  selector: '[print-if-defined]'
})
export class PrintIfDefinedDirective {

  constructor(private el: ElementRef) { }

  @Input('suffix') 
  suffix:string;

  @Input('value') 
  set value(nm:number) {
    this.el.nativeElement.style.display = nm || nm === 0 ? "" : "none";
    this.el.nativeElement.textContent =  nm + (this.suffix ? ' ' + this.suffix : '');
  }

}

并像

一样使用它
<div print-if-defined [value]="event?.daysRemaining" suffix="days"></div>

您可以在以下位置看到所有 运行: https://plnkr.co/edit/gFeKJilYGdt5ttENjKUG?p=preview