Angular中如何避免*ngFor循环里的[(ngModel)]绑定到全部输入框?
问题根因
你当前的hideEdit、newTitle都是组件全局变量,所有*ngFor渲染的购物车条目共享这两个变量,所以触发任意条目的编辑操作,所有条目都会同步显示编辑框、绑定同一个输入值,这和[(ngModel)]本身无关,是状态作用域的问题。
可行解决方案
方案1:给条目绑定独立状态(推荐,可保留ngModel用法)
给Album实体新增isEditing(布尔型,标记当前条目是否处于编辑状态)、editingTitle(字符串型,存当前条目临时编辑的标题)两个字段,每个条目独立维护自己的编辑状态。
模板代码修改:
<div class="container my-5"> <h1>Your Cart</h1> <div *ngFor="let item of listAlbums" class="container"> <div class="row"> <div class="col-md-4"> <h6>Item name: {{item.title}}</h6> <img src="{{item.thumbnailUrl}}"> <input class="form-control" type="number" value="{{item.quantity}}"> <button (click)="remove(item)" class="btn btn-danger mx-3">X</button> <button (click)="edit(item)" class="btn btn-warning">Edit</button> <input type="text" placeholder="{{item.title}}" [(ngModel)]="item.editingTitle" [hidden]="!item.isEditing"> </div> </div> </div>
业务代码修改:
@Component({ selector: 'app-cart', templateUrl: './cart.component.html', styleUrls: ['./cart.component.scss'] }) export class CartComponent implements OnInit { listAlbums:Album[]=[] constructor(private productService:ProductService) { } ngOnInit() { this.productService.itemList.subscribe(data=> { // 初始化时给每个条目加默认的编辑状态字段 this.listAlbums = data.map(item => ({...item, isEditing: false, editingTitle: item.title})) }) } remove(item:Album) { this.productService.removeItem(item) } edit(item:Album) { // 先把其他条目的编辑态关掉,保证同一时间只有一个条目在编辑 this.listAlbums.forEach(album => album.isEditing = false) item.isEditing = !item.isEditing // 如果是提交编辑,就把编辑后的标题同步到原字段 if(!item.isEditing) { item.title = item.editingTitle this.productService.editItem(item, item.editingTitle) } } }
方案2:无需修改Album实体,用全局变量标记当前编辑条目
新增editingItemId变量存储当前正在编辑的条目ID,无需给每个条目加额外字段。
业务代码新增变量:
// 假设Album实体有唯一字段id editingItemId: number | null = null newTitle: string = ''
模板判断逻辑修改:
<input type="text" placeholder="{{item.title}}" [(ngModel)]="newTitle" [hidden]="item.id !== editingItemId">
edit方法修改:
edit(item:Album) { if(this.editingItemId === item.id) { // 提交编辑 this.productService.editItem(item, this.newTitle) this.editingItemId = null this.newTitle = '' } else { // 开启当前条目编辑,初始化输入框值 this.editingItemId = item.id this.newTitle = item.title } }
方案3:完全不用ngModel的实现
用模板引用变量直接获取输入框的值,无需双向绑定:
模板修改:
<input type="text" #editInput [placeholder]="item.title" [hidden]="item.id !== editingItemId"> <button (click)="edit(item, editInput.value)" class="btn btn-warning">Edit</button>
业务代码edit方法修改:
edit(item:Album, inputValue: string) { if(this.editingItemId === item.id) { this.productService.editItem(item, inputValue) this.editingItemId = null } else { this.editingItemId = item.id } }
内容的提问来源于stack exchange,提问作者Naranpurev Munkhbayar
相关产品推荐
相关产品推荐

