在Angular 2或4中有条件地使输入字段只读:建议+最佳/哪种方法可以实现它

50

我试图回答别人的问题。在尝试回答的过程中,我意识到自己对一些事情存在相当多的不确定性。

我希望有人可以就以下编号为1..4的问题提供反馈:

任务:根据条件将输入字段设置为只读

HTML 的相关部分:

<input type="text" placeholder="Club Name" #clubName>

将此添加到 TypeScript 组件中。

// class properties
@ViewChild('clubName')
inp:HTMLInputElement; // Could also use interface Element

// conditionally set in some other methods of class
inp.setAttribute('readonly', 'readonly');
inp.removeAttribute('readonly');

我必须说这对我来说是一个灰色地带。

  1. 在Angular 2+中,直接使用@ViewChild引用HTMLInputElementElement是否是不好的实践?我经常看到示例使用ElementRef或从ElementRef链接到nativeElement

由于VS Studio没有针对它们的智能感知,所以我突然感觉自己像在黑暗中编码。例如,您永远无法获得有关方法setAttribute或removeAttribute及其参数要求等的反馈。(我知道也可以使用类型转换)


  1. 然后,在查看文档后,我怀疑您可以直接在HTML模板中对输入执行此操作:

<input [attr.readonly]= "isReadOnly">

据我所知,使用Typescript时需要通过一个属性获取器来实现这个功能:

get isReadOnly() :boolean {
}

这种方式有效吗?


  1. 我在想,你能否在HTML模板中使用方法语法:

<input [attr.readonly]= "isReadOnly()">

类型脚本

isReadOnly() :boolean {
}

这种方法有效吗?


4. 总之,什么是最好的方法?

更新:还有一个 *ngIF,因此您可以输出具有相同名称的两个输入元素中的一个。但对我来说,这听起来像是杀鸡焉用牛刀。


定义有效的...因为如果你在问它是否有效,那就测试一下,找出答案。这是一个非常广泛的问题...我在不同的场合使用 2&3,取决于我需要计算什么来确定布尔值。 - Zze
9个回答

122

你需要使用以下内容(Angular 4):

<input [readonly]="isReadOnly">
如果您使用att.readonly,则无论其值为何,输入都将始终为只读,因为readonly属性将存在。通过使用[readonly],Angular仅在isReadOnly为true时才会设置该属性。
在HTML中,以下内容足以使输入框变为只读:
<input readonly>

这个可行!由于我的条件取决于FormControl的值,并且我必须将数据共享到子组件中,所以最终需要一些额外的代码。在父模板中:<child-component [isReadOnly]="isSomeFormControlName.value === 'true'">并在我的子组件中添加以下代码: @Input() isReadOnly: boolean; - MikhailRatner

4

这些方法都对我不起作用,最终我通过创建自定义指令来解决问题。指令是Angular的一个强大功能。

  1. 创建自定义指令

@Directive({
  selector: '[readonly],[readOnly]',
  host: {
    '[attr.readonly]': '_isReadonly ? "" : null'
  }
})
class ReadonlyDirective {
  _isReadonly = false;

  @Input() set readonly (v) {
     this._isReadonly = coerceBooleanProperty(v);
  };

  ngOnChanges(changes) {
    console.log(changes);
  }
}

  1. 将其添加到模块声明中

@NgModule({
  ...
  declarations: [ ..., ReadonlyDirective ],
  ...
})

3. Now its time to use directive as following.

<input [(ngModel)]="name" [readonly]="isReadonly" />
or
<input [(ngModel)]="name" readonly />

Directives are powerful feature of angular, I strongly recommend you to go through https://angular.io/guide/attribute-directives

Demo https://stackblitz.com/edit/angular-readonly-input-aifncy?file=src/app/app.component.ts


4

一切都取决于你想要实现什么。乍一看,我会说pct. 2是最简单的方法:

<input [attr.readonly]= "isReadOnly">

然后,在你的组件上声明变量:

声明方式如下:

isReadOnly: boolean;

在此之后,您可以根据自己的意愿分配值:
// when you want to be read-only
isReadOnly = true;
// whe you want to be editable
isReadOnly = false;

4
如果您使用att.readonly,则输入始终为只读,因为即使其值为false,readonly属性也会存在。通过使用[readonly],Angular仅在isReadOnly为true时才会添加该属性。 这个答案是错误的,请阅读被接受的答案。 - Tushar Khanna

2

很多时候,如果为false(例如因为样式或继承功能),您可能不需要readonly属性存在。您可以通过将值设置为null来实现:

[readonly]="shouldBeReadonly ? 'readonly' : null"

null会从元素中删除属性。


0

我已经修复好了 :)

<input matInput type="text" (focus)="userNameFocus()" placeholder="Username" #u1 formControlName="userName" autocomplete="off" />

// initialize form on userName focus
<input matInput [type]="inputType" style="-webkit-text-security: square;" #p2 formControlName="password" />

0

有一个更简单的解决方案,只需使用

@Input('readonly') readonly: boolean
ngOnInit(){
  this.readonly= this.readonly!== undefined && this.readonly!== false
}

现在你的组件上的readonly属性将会是:

false:
<app-component>
<app-component [readonly]='false'>

true:
<app-component readonly>
<app-component [readonly]='true'>

我担心我发现@phn在2017年发布的解决方案要简单得多! - JGFMK

0
当我尝试了最佳答案中的解决方案时,我遇到了以下错误:
Can't bind to 'readOnly' since it isn't a known property of 'select'.ngtsc(-998002)

最终对我起作用的解决方案是:
[attr.readonly]="isReadonly() ? true : null"

我认为“attr.”是必要的,并且“null”是必要的,以完全移除只读属性(而不仅仅设置为false,这仍然使元素只读)。


这并没有提供问题的答案。一旦你获得足够的声望,你就能够评论任何帖子;相反,提供不需要提问者进一步澄清的答案。- 来自审核 - dcolazin

-1

您可以使用<input readonly="{{ variable }}>"

在您的*.component.ts中,初始化变量:

private variable: boolean = true;

3
无论variable的值如何,都会向输入框添加只读属性。 - lortimer

-1

component.html

<input matInput formControlName="status" [readonly]="!status" />

component.ts

// when you want to be read-only
isReadOnly = true;
// whe you want to be editable
isReadOnly = false;

为什么更改 isReadOnly 会对 HTML 输入或 formControl 产生影响?在您的示例中,没有任何内容绑定到 isReadOnly - Erik Philips

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