ngModel 不适用于 ngFor 中的输入类型复选框
Posted
技术标签:
【中文标题】ngModel 不适用于 ngFor 中的输入类型复选框【英文标题】:ngModal not working for input type checkbox inside ngFor 【发布时间】:2019-06-12 11:46:34 【问题描述】:在 ngFor 中使用复选框时,ngModal 似乎不起作用,而 重复一个对象数组,如
["checked":true,"checked":false]
如果我们将组件中的 checked 属性更改为 true 或 false,它不会反映在 UI 中,同样的逻辑将适用于 md bootstrap 的 mdb-checkbox。
app.component.ts
import Component from '@angular/core';
@Component(
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
)
export class AppComponent
sampleObj = [
'checked': false, name: 'option 1',
'checked': false, name: 'option 2',
'checked': false, name: 'option 3',
'checked': true, name: 'option 4'
];
sampleFunc(event, i)
if (event.currentTarget.checked)
alert(i);
this.sampleObj[i].checked = false;
app.component.html
<div *ngFor="let item of sampleObj; let i = index">
<input type='checkbox' name='itemi' [(ngModel)]="item.checked" (change)="sampleFunc($event, i)" />
<label for='itemi'><span>item.name</span></label>
</div>
工作示例 https://stackblitz.com/edit/angular-3orv4w
角度版本:
Angular CLI: 7.1.1
Node: 10.14.2
OS: win32 x64
Angular: 7.1.1
... animations, cdk, cli, common, compiler, compiler-cli, core
... forms, language-service, material, platform-browser
... platform-browser-dynamic, router
Package Version
-----------------------------------------------------------
@angular-devkit/architect 0.11.1
@angular-devkit/build-angular 0.12.1
@angular-devkit/build-optimizer 0.12.1
@angular-devkit/build-webpack 0.12.1
@angular-devkit/core 7.1.1
@angular-devkit/schematics 7.1.1
@angular/pwa 0.11.2
@angular/service-worker 7.1.2
@ngtools/webpack 7.2.1
@schematics/angular 7.1.1
@schematics/update 0.11.1
rxjs 6.3.3
typescript 3.1.6
webpack 4.23.1
【问题讨论】:
不清楚你在问什么。我使用了你的 stackblitz-Demo 并且它有效?!请更准确地说明您期望的行为。 @Lynx242 我的意思是基于 sampleObj 的选中属性,复选框应该可以工作。即来自组件,如果我们将已选中的属性更改为 true 以假设 sampleObj[2],UI 中的第三个复选框应该将其状态更改为 true 对吗?因为使用了 ngModel。 抱歉耽搁了,我有一些约会。请在下面找到我的解决方案。 【参考方案1】:好的,我有一个解决方案。显然,Angular 内部并未将检查状态视为布尔值。
我做了以下事情:
我在您的 HTML 文件中添加了一个按钮,就在结束标记 </div>
之后。仅用于测试目的。
<button (click)="toggle()">click me</button>
在 TypeScript-File 中,我添加了一个带有以下内容的切换方法。
toggle(): void
this.sampleObj[1].checked = !this.sampleObj[1].checked;
这就是诀窍。
【讨论】:
感谢 Lynx,您的解决方案有效,但它仍然无法在 ngModelChange 中运行,也无法更改事件处理程序。如果我们更改 this.sampleObj[1].checked = !this.sampleObj[1].checked;它不会反映。 对不起,你有点失去我了。每当您单击这些复选框之一时,都会调用您的sampleFunc()
。但我不明白你为什么要在它们刚刚被检查时将它们重置为未选中?这背后的策略/用例是什么?
PS:当(change)
触发时,您无法切换状态,因为此时您处于ngOnChanges()
-hook 中。 Angular 不接受将值切换回此特定状态。 angular.io/guide/lifecycle-hooks
有什么办法可以实现吗?我能够使用 mdb-bootstrap 在更改事件中工作,但是对于典型的输入元素,它不起作用。【参考方案2】:
好的,就这样吧。这是你的 stackblitz-class 修改和评论。
为了达到你的目标,你可以做的是暂时记住当前点击的复选框的索引。我用变量marker
做到了这一点。
我几乎不建议在您开始操作该框之前等待ngAfterViewChecked()
-hook,因为这样您可以确保在页面变慢时不会出现任何时间问题。
下一步是检查是否设置了标记。然后你必须将你的实际切换回代码包装到一个超时函数中。如果你不这样做,你会遇到这个错误:
ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后已更改。以前的值:“模型:真”。当前值:'model: false'。
就是这样。
您可以尝试进一步减少超时,以使复选框甚至不闪烁。但请始终注意,如果您行动过快,可能会遇到上述错误。
import Component from '@angular/core';
@Component(
selector: 'my-app',
templateUrl: './app.component.html',
styleUrls: [ './app.component.css' ]
)
export class AppComponent
// the clicked checkbox's index
private marker: number = -1;
sampleObj = [
'checked': false, name: 'option 1',
'checked': false, name: 'option 2',
'checked': false, name: 'option 3',
'checked': true, name: 'option 4'
];
sampleFunc(event, i)
if (event.currentTarget.checked)
// memorize the clicked checkbox's index
this.marker = i;
toggle() : void
this.sampleObj[1].checked = !this.sampleObj[1].checked;
ngAfterViewChecked(): void
// if a marker is set
if (this.marker > -1)
// start the timeout and then reset the checkbox
setTimeout (() =>
this.sampleObj[this.marker].checked = !this.sampleObj[this.marker].checked;
this.marker = -1;
, 20);
【讨论】:
希望这会有所帮助。如果它解决了您的问题,请不要忘记将此答案标记为解决方案。 别提了。 ;o)以上是关于ngModel 不适用于 ngFor 中的输入类型复选框的主要内容,如果未能解决你的问题,请参考以下文章
*ngFor 如何使用索引将数组中的每个项目绑定到 ngModel
Angular2,Ionic2:如何使用 ngModel 对嵌套 *ngfor 中的单选按钮进行 2way 绑定?