Angular 2 [disabled] 只对部分控件有效
Angular 2 [disabled] only works on some controls
我有一个大表单,它是根据服务器提供的数据动态生成的。要生成单选按钮,我使用以下 HTML:
<ng-container *ngSwitchCase="'RADIO'">
<td *ngFor="let option of item.SelectOptions">
<div class="input-group">
<input type="radio"
[(ngModel)]="item.PricingSelectIndex"
name="{{ item.UIName }}RadioButton"
id="{{ item.UIName }}{{ option.PricingSelectIndex }}"
[value]="option.PricingSelectIndex"
[disabled]="item.ReadonlyTF"
(click)="saveField(item.UIName, 'SelectIndex', option.PricingSelectIndex)" />
<label for="{{ item.UIName }}{{ option.PricingSelectIndex }}" style="margin-left: 5px;">
{{ option.Label }}
<i class="fa fa-question-circle" [tooltip]="item.TooltipText" placement="right" *ngIf="item.TooltipText"></i>
</label>
</div>
</td>
</ng-container>
显然这是一个较大页面的一部分,它查看数据中的每个项目并根据项目的 ControlType 属性-- 这是单选按钮的 HTML 生成表单。数据项包括一个名为 ReadonlyTF 的 属性,它告诉我是否应禁用该控件(例如只读)。然后该项目包含一个 SelectOptions 属性,它是一组较小的项目,每个项目都映射到集合中的一个单选按钮。 (因此,例如,我遇到问题的控件有两个 SelectOptions,一个用于是,一个用于否。)因此,每个单选按钮都使用相同的 HTML.
生成
奇怪的是。在相关控件中,生成的第一个单选按钮被禁用(这是我想要的),但第二个不是。
如果仔细观察,您会发现 Yes 被禁用但 No 没有!下面是两个控件在 Chrome 的“元素”选项卡中的呈现方式:
两者都包含 ng-reflect-is-disabled="true"
但实际上只有第一个被禁用。第二个按钮丢失 ng-reflect-value
。同样,这些是使用完全相同的 HTML 片段呈现的。
我正在使用 Angular 2.4.6、Typescript 2.1.5、bootstrap 3.3.7 和 angular-cli 进行编译。组件中没有支持 TS 会影响这一点:我获取数据并将其弹出到 属性 中,然后由 HTML 模板获取,仅此而已。我认为这可能是某种变化检测问题,但用 changeDetectorRef.detectChanges()
强制它没有做任何事情。我对此感到困惑,但我无法让任何人点击活动的单选按钮!
谢谢!
发生这种情况的原因是因为您有多个带有 NgModel
指令和相同 name
属性的输入元素。 NgModel 的内部逻辑根据 disabled
输入的值在表单控件上切换 disable()
和 enable()
。由于名称冲突,您只有一个表单控件,因此在更远的地方只有第一个元素得到更新。
使名称属性唯一,您的问题就会消失。
如果您查看 ng_model.ts 的源代码,您可以逐步了解此行为。
我知道这是一个糟糕的解决方案,但它会有所帮助:
<input *ngIf="shouldBeDisabled" name="foo" disabled>
<input *ngIf="!shouldBeDisabled" name="foo">
我有一个大表单,它是根据服务器提供的数据动态生成的。要生成单选按钮,我使用以下 HTML:
<ng-container *ngSwitchCase="'RADIO'">
<td *ngFor="let option of item.SelectOptions">
<div class="input-group">
<input type="radio"
[(ngModel)]="item.PricingSelectIndex"
name="{{ item.UIName }}RadioButton"
id="{{ item.UIName }}{{ option.PricingSelectIndex }}"
[value]="option.PricingSelectIndex"
[disabled]="item.ReadonlyTF"
(click)="saveField(item.UIName, 'SelectIndex', option.PricingSelectIndex)" />
<label for="{{ item.UIName }}{{ option.PricingSelectIndex }}" style="margin-left: 5px;">
{{ option.Label }}
<i class="fa fa-question-circle" [tooltip]="item.TooltipText" placement="right" *ngIf="item.TooltipText"></i>
</label>
</div>
</td>
</ng-container>
显然这是一个较大页面的一部分,它查看数据中的每个项目并根据项目的 ControlType 属性-- 这是单选按钮的 HTML 生成表单。数据项包括一个名为 ReadonlyTF 的 属性,它告诉我是否应禁用该控件(例如只读)。然后该项目包含一个 SelectOptions 属性,它是一组较小的项目,每个项目都映射到集合中的一个单选按钮。 (因此,例如,我遇到问题的控件有两个 SelectOptions,一个用于是,一个用于否。)因此,每个单选按钮都使用相同的 HTML.
生成奇怪的是。在相关控件中,生成的第一个单选按钮被禁用(这是我想要的),但第二个不是。
如果仔细观察,您会发现 Yes 被禁用但 No 没有!下面是两个控件在 Chrome 的“元素”选项卡中的呈现方式:
两者都包含 ng-reflect-is-disabled="true"
但实际上只有第一个被禁用。第二个按钮丢失 ng-reflect-value
。同样,这些是使用完全相同的 HTML 片段呈现的。
我正在使用 Angular 2.4.6、Typescript 2.1.5、bootstrap 3.3.7 和 angular-cli 进行编译。组件中没有支持 TS 会影响这一点:我获取数据并将其弹出到 属性 中,然后由 HTML 模板获取,仅此而已。我认为这可能是某种变化检测问题,但用 changeDetectorRef.detectChanges()
强制它没有做任何事情。我对此感到困惑,但我无法让任何人点击活动的单选按钮!
谢谢!
发生这种情况的原因是因为您有多个带有 NgModel
指令和相同 name
属性的输入元素。 NgModel 的内部逻辑根据 disabled
输入的值在表单控件上切换 disable()
和 enable()
。由于名称冲突,您只有一个表单控件,因此在更远的地方只有第一个元素得到更新。
使名称属性唯一,您的问题就会消失。
如果您查看 ng_model.ts 的源代码,您可以逐步了解此行为。
我知道这是一个糟糕的解决方案,但它会有所帮助:
<input *ngIf="shouldBeDisabled" name="foo" disabled>
<input *ngIf="!shouldBeDisabled" name="foo">