ngModel 不适用于 ngFor 中的输入类型复选框
ngModal not working for input type checkbox inside ngFor
ngModal 在 ngFor 中使用复选框时似乎不起作用,而
重复对象数组,例如
[{"checked":true},{"checked":false}]
如果我们从组件中将选中的 属性 更改为 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='item{{i}}' [(ngModel)]="item.checked" (change)="sampleFunc($event, i)" />
<label for='item{{i}}'><span>{{item.name}}</span></label>
</div>
工作示例
https://stackblitz.com/edit/angular-3orv4w
Angular版本:
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
好的,我有办法了。显然,Angular 不会在内部将检查状态视为布尔值。
我做了以下事情:
我在您的 HTML 文件中添加了一个按钮,就在结束标记 </div>
之后。仅供测试。
<button (click)="toggle()">click me</button>
在 TypeScript 文件中,我添加了一个具有以下内容的切换方法。
toggle(): void {
this.sampleObj[1].checked = !this.sampleObj[1].checked;
}
这样就可以了。
好的,开始吧。这是你的 stackblitz-class 修改和评论。
为了达到你的目的,你可以做的是暂时记住当前点击的复选框的索引。我用变量 marker
做了这个。
我几乎不建议在开始操作盒子之前等待 ngAfterViewChecked()
-hook,因为这样你可以确保你不会 运行 出现任何时间问题,如果页面有时会变慢。
下一步是检查标记是否已设置。然后您必须将实际的切换回代码包装到超时函数中。如果不这样做,您将 运行 出现此错误:
ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后发生了变化。以前的值:'model: true'。当前值:'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);
}
}
}
ngModal 在 ngFor 中使用复选框时似乎不起作用,而 重复对象数组,例如
[{"checked":true},{"checked":false}]
如果我们从组件中将选中的 属性 更改为 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='item{{i}}' [(ngModel)]="item.checked" (change)="sampleFunc($event, i)" />
<label for='item{{i}}'><span>{{item.name}}</span></label>
</div>
工作示例 https://stackblitz.com/edit/angular-3orv4w
Angular版本:
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
好的,我有办法了。显然,Angular 不会在内部将检查状态视为布尔值。
我做了以下事情:
我在您的 HTML 文件中添加了一个按钮,就在结束标记 </div>
之后。仅供测试。
<button (click)="toggle()">click me</button>
在 TypeScript 文件中,我添加了一个具有以下内容的切换方法。
toggle(): void {
this.sampleObj[1].checked = !this.sampleObj[1].checked;
}
这样就可以了。
好的,开始吧。这是你的 stackblitz-class 修改和评论。
为了达到你的目的,你可以做的是暂时记住当前点击的复选框的索引。我用变量 marker
做了这个。
我几乎不建议在开始操作盒子之前等待 ngAfterViewChecked()
-hook,因为这样你可以确保你不会 运行 出现任何时间问题,如果页面有时会变慢。
下一步是检查标记是否已设置。然后您必须将实际的切换回代码包装到超时函数中。如果不这样做,您将 运行 出现此错误:
ExpressionChangedAfterItHasBeenCheckedError:表达式在检查后发生了变化。以前的值:'model: true'。当前值:'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);
}
}
}