当属性存在且为空时,使 Angular 2 组件输入“true”

Ben*_*lts 6 javascript angular2-template angular

考虑一个 Angular 2 组件,它的@Input意思是一个布尔值,它的存在表示true,不存在表示false。现在,我可能会使用自定义的 getter/setter 来管理它,或者通过一个函数来告诉我该属性是否存在:

@Component({
  selector:'foo',
  template:`<div [class.error]="hasError()">Hello world</div>`
})
class Foo {
  @Input() error:string;
  public hasError() {
    return error === '' || !!error;
  }
}
Run Code Online (Sandbox Code Playgroud)

然后我可以在另一个组件中使用它,如下所示:

<foo></foo> <!-- no error class -->
<foo error></foo> <!-- has error class -->
Run Code Online (Sandbox Code Playgroud)

我真正想做的是这个,但有相同的行为:

@Component({
  selector:'foo',
  template:`<div [class.error]="error">Hello world</div>`
})
class Foo {
  @Input() error:boolean;
}
Run Code Online (Sandbox Code Playgroud)

在我的第一个示例中,是否有一种通用模式可以在没有样板的情况下创建这种行为?

Shl*_*saf 2

您需要的是一个装饰器,它将您的布尔属性包装为 getter/setter 并处理所有逻辑。

这很简单,保存样板文件即可。

此功能已经由 google 的材料团队实现,他们为 Angular 2 构建了材料库,并与 Angular 团队密切合作。

目前它是在他们的仓库中实现的,而不是在 Angular 仓库中,但如果需求增加,我想他们可能会考虑将其迁移到 Angular,以前在某些情况下已经这样做了。

不管怎样,这非常简单,大约需要 15-20 LOC。

/**
 * Annotation Factory that allows HTML style boolean attributes. For example,
 * a field declared like this:
 * @Directive({ selector: 'component' }) class MyComponent {
 *   @Input() @BooleanFieldValueFactory() myField: boolean;
 * }
 *
 * You could set it up this way:
 *   <component myField>
 * or:
 *   <component myField="">
 */
function booleanFieldValueFactory() {
  return function booleanFieldValueMetadata(target: any, key: string): void {
    const defaultValue = target[key];
    const localKey = `__md_private_symbol_${key}`;
    target[localKey] = defaultValue;

    Object.defineProperty(target, key, {
      get() { return (<any>this)[localKey]; },
      set(value: boolean) {
        (<any>this)[localKey] = value != null && `${value}` !== 'false';
      }
    });
  };
}


export { booleanFieldValueFactory as BooleanFieldValue };
Run Code Online (Sandbox Code Playgroud)

您可以在此链接中查看实现