我们正在开发组件,并且在使用它们时,我们希望使用与DOM节点相同的机制来有条件地定义属性。因此,为完全防止出现属性,我们将值设置为null,而该值在最终的HTML输出中不存在。太好了!
<button [attr.disabled]="condition ? true : null"></button>
现在,当使用我们自己的组件时,这不起作用。设置null
时,实际上在组件@Input中获得null
作为值。默认情况下,任何设置值都将被覆盖。
...
@Component({
selector: 'myElement',
templateUrl: './my-element.component.html'
})
export class MyElementComponent {
@Input() type: string = 'default';
...
<myElment [type]="condition ? 'something' : null"></myElement>
因此,每当我们读取组件中的type
时,我们都会得到null
而不是设置的'default'
值。
我试图找到一种方法来获取原始默认值,但没有找到它。在ngBaseDef
时间访问时,它存在于constructor
中,但是在生产环境中不起作用。我希望ngOnChanges
在完成的第一个更改中为我提供真实的(默认)值,因此能够防止设置null
,但是previousValue
是{{1} }。
我们想出了一些解决方法:
undefined
对象,并为每个输入设置default
时的默认值null
<myElement #myelem [type]="condition ? 'something' : myelem.type"></myElement>
但是很好奇,如果还有其他人也有类似的问题以及如何解决。我也将不胜感激任何其他更优雅的想法。
谢谢!
答案 0 :(得分:1)
没有标准的角度方法,因为很多时候您都希望将null
或undefined
作为值。您的想法不是不好的解决方案。我还有几个
ngOnChanges
挂钩:@Input()
type: string = 'defaultType';
ngOnChanges(changes: SimpleChanges): void {
// == null to also match undefined
if (this.type == null) {
this.type = 'defaultType';
}
}
Observables
:private readonly _type$ = new BehaviorSubject('defaultType');
readonly type$ = this._type$.pipe(
map((type) => type == null ? 'defaultType' : type)
);
@Input()
set type(type: string) {
this._type$.next(type);
}
function Default(value: any) {
return function(target: any, key: string | symbol) {
const valueAccessor = '__' + key.toString() + '__';
Object.defineProperty(target, key, {
get: function () {
return this[valueAccessor] != null ? this[valueAccessor] : value
},
set: function (next) {
if (!Object.prototype.hasOwnProperty.call(this, valueAccessor)) {
Object.defineProperty(this, valueAccessor, {
writable: true,
enumerable: false
});
}
this[valueAccessor] = next;
},
enumerable: true
});
};
}
您可以这样使用:
@Input()
@Default('defaultType')
type!: string;
答案 1 :(得分:0)
您可以在父组件中使用三元运算符,如下所示:
<myElment [attr.type]="condition ? 'something' : null"></myElement>
只有在满足条件的情况下,这才会将值传递给子组件,否则初始化值将不会被覆盖
子组件中不需要任何其他代码
问题是您可能会掉毛能力
答案 2 :(得分:0)
如果需要对多个输入执行此操作,则还可以使用自定义score3
来代替手动定义每个输入的getter / setter和默认值。如果输入为pipe
,则pipe
可以包含逻辑和defaultArg以返回defaultArg。
即
null
// pipe
@Pipe({name: 'ifNotNullElse'})
export class IfNotNullElsePipe implements PipeTransform {
transform(value: string, defaultVal?: string): string {
return value !== null ? value : defaultVal;
}
}
答案 3 :(得分:0)
基于Poul Krujit解决方案,又一个选择(如果您不想实现自己的自定义@annotation,则可能更简单):
const DEFAULT_VALUE = 'default';
export class MyElementComponent {
typeWrapped = DEFAULT_VALUE;
@Input()
set type(selected: string) {
// this makes sure only truthy values get assigned
// so [type]="null" or [type]="undefined" still go to the default.
if (selected) {
this.typeWrapped = selected;
} else {
this.typeWrapped = DEFAULT_VALUE;
}
}
get type() {
return this.typeWrapped;
}
}