将布尔值输入到Angular 2组件中

50

我正在尝试编写一个可重用于我的应用程序中的组件,有时将显示控制按钮,有时则不会。

理想情况下,我希望从属性的存在或不存在中获取它,以便使用该组件看起来像<generic-component hideControls></generic-component>,并在我的组件中基于该属性是否存在而设置布尔变量,但我无法找到一种方法来实现这一点。

有什么办法可以做到这一点吗?

我尝试了以下稍微复杂一点的版本(虽然理想情况下我不需要在showControls / hideControls上设置值);

generic.component.html

<div>
  <div>Stuff</div>
  <div *ngIf="showControls">Controls</div>
</div>

通用组件.generic.component.ts

// imports etc.
@Component({
  selector: 'generic-selector',
  templateUrl: 'generic.component.html'
})
export class GenericComponent implements OnInit {
  @Input()
  public showControls: boolean = true;

  // other inputs and logic
}

这种方式失败了,因为使用<generic-selector showControls="false"></generic-selector>将showControls设置为字符串"false",它是真值,而不是布尔值。因此,我必须在组件中添加大量混乱的代码来获取输入并根据是否提供字符串"false"来将其转换为布尔值。希望有一种更简洁的方法来解决这个问题,但我更喜欢上面提到的另一种选项。

4个回答

58
这个失败了,因为使用<generic-selector showControls="false"></generic-selector>将showControls设置为字符串"false",而不是布尔值。所以我必须通过在组件中添加很多混乱来接收输入并根据是否给出字符串"false"来转换为布尔值。希望有一种不那么凌乱的方法解决这个问题,但我更喜欢上面提到的另一种方法。

使用绑定

<generic-selector [showControls]="false"></generic-selector>

7
[showControls]="false" 可以正常工作。但是 showControls={{false}} 是不起作用的。 - Maz T
在这里了解更多关于括号属性的内容:https://dev59.com/B1sV5IYBdhLWcg3wrAZJ - SeanMC
解决方案完美运行,但为什么Angular不将false视为变量?有人能解释一下吗? - Abhijit Jagtap
@AbhijitJagtap false 是 JavaScript 中的保留关键字,不能用作变量名。 - andii1997

39

您可以像使用其他属性一样使用Input修饰符。唯一的诀窍是,当属性不存在时,值将为undefined,否则值将为空字符串。

逻辑:

import { Component, OnInit } from '@angular/core';

@Component({
  selector: '',
  templateUrl: './boolean-component.component.html'
})
export class AppBooleanComponent implements OnInit {

  @Input('boolean-attribute') booleanAttr: boolean;

  ngOnInit() {
    this.booleanAttr = this.booleanAttr !== undefined;
    console.log(`Boolean attribute is ${this.booleanAttr ? '' : 'non-'}present!`);
  }

}

模板1(记录“布尔属性已存在!”):

<app-boolean-component boolean-attribute></app-boolean-component>

模板2(记录“布尔属性不存在!”):

<app-boolean-component></app-boolean-component>

16

在Angular中,有两种将值分配给属性的方法:

  1. 使用HTML属性
  2. 使用方括号

在第一种情况下,您的属性的值始终是一个字符串,就像每个HTML属性一样,即使您赋予可插值的字符串,如: {{true}}

而在第二种情况下,它将被解释为JavaScript表达式,但在您的上下文中。因此,如果您在那里有一个对象符号,那么您属性的值将被解析为一个对象。但是,为了指定上下文,Angular不使用“with”语句,所以您不能在那里使用全局变量,而只能使用组件属性,该组件属性是插入您组件的范围内的。

<generic-selector [showControls]="false"></generic-selector>

在这种情况下,它会把字符串“false”转换为JavaScript。所以在JavaScript中,它是一个布尔值,然后你会得到一个 boolean

但是,如果您有这样的东西: <generic-selector [showControls]="{myProp: 'val'}"></generic-selector>

那么您的showControls的类型将是 object ,并且它的值将具有myProp属性等于'val'。

但是,如果您这里有一些非文字定义的东西,那么它将被视为您类的属性:

<generic-selector [showControls]="location"></generic-selector>

然后,如果您在包含 generic-selector 的组件的作用域中具有位置属性,则将取其位置属性的值,否则将为未定义。

我建议您考虑使用ngOnInit来记录分配的属性类型和值。


2
使用Angular 16.1或更高版本,您可以在@Input()上使用transform选项,并使用booleanAttribute函数来处理输入的转换为布尔值。
import {Component, Input, booleanAttribute} from '@angular/core';

@Component({
  selector: 'generic-selector',
  templateUrl: 'generic.component.html'
})
export class GenericComponent implements OnInit {
  @Input({transform: booleanAttribute}) showControls = false;

  // other inputs and logic
}

更多细节请参阅添加了该功能的拉取请求

在这篇文章中添加了注释和演示:https://fireflysemantics.medium.com/angular-boolean-coercion-with-the-new-input-transform-feature-c6aaf5e5c989 - undefined

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接