You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Angular:修改克隆DOM元素的ng-model值,解决克隆元素同步问题

解决Angular克隆模板后共享ng-model的问题

你碰到的问题很典型:所有通过ng-template克隆出来的元素都绑定到组件类里同一个questiontype变量,所以任何一个下拉菜单的选择都会同步到所有克隆实例上。要解决这个问题,核心思路是给每个克隆项分配独立的状态数据,让它们绑定到各自的变量,而不是共享组件级的全局变量。

下面是具体的修改步骤:

1. 修改TypeScript代码

首先,我们需要存储每个克隆项的独立状态,并且在创建视图时传递专属的上下文:

import { Component, ViewChild, TemplateRef, ViewContainerRef } from '@angular/core';

@Component({
  // ...你的组件元数据
})
export class YourComponent {
  @ViewChild('clone') template: TemplateRef<any>;
  @ViewChild('container', { read: ViewContainerRef }) container: ViewContainerRef;
  
  // 存储每个克隆项的独立状态,初始包含一个默认项(对应首次显示的内容)
  private clonedQuestionItems: Array<{ questiontype: string }> = [{ questiontype: 'multiplechoice' }];

  ngAfterViewInit() {
    // 初始化时渲染第一个默认项
    this.renderItems();
  }

  cloneTemplate() {
    // 添加新的克隆项,默认类型为multiplechoice
    this.clonedQuestionItems.push({ questiontype: 'multiplechoice' });
    // 重新渲染所有项(确保视图和数据同步)
    this.renderItems();
  }

  changeOptions(item: { questiontype: string }, newType: string) {
    // 修改当前项的类型,而非全局变量
    item.questiontype = newType;
  }

  private renderItems() {
    // 清空容器后重新渲染所有项
    this.container.clear();
    this.clonedQuestionItems.forEach(item => {
      const view = this.template.createEmbeddedView({ $implicit: item });
      this.container.insert(view);
    });
  }
}

2. 修改HTML模板

接下来,让模板接收每个项的上下文数据,绑定到各自的questiontype属性:

<!-- 承载克隆视图的容器 -->
<div #container></div>

<ng-template #clone let-item>
  <div class="mask1" *ngIf="question1 === true">
    <div class="">
      <div style="margin-left:15px">
        <div class="row margin-top-10">
          <div class="col-lg-1 col-sm-1 col-md-1 col-xs-1 ">
            <button mat-mini-fab class="oval"> 
              <!-- 显示项的序号,基于数组索引 -->
              {{ clonedQuestionItems.indexOf(item) + 1 }} 
            </button>
          </div>
          <div class="col-lg-5 col-sm-5 col-md-5 col-xs-5 how-do-you-feel margin-top-10 "> 
            How do you feel? <div class="line"></div> 
          </div>
          <div class="col-lg-6 col-sm-6 col-md-6 col-xs-6 ">
            <div class="col-xs-11">
              <!-- 判断当前项的类型,而非全局变量 -->
              <mat-radio-button class="pull-right" value="1" *ngIf="item.questiontype === 'multiplechoice'">
              </mat-radio-button>
              <mat-form-field class="choices">
                <!-- 绑定到当前项的questiontype属性 -->
                <mat-select [(ngModel)]="item.questiontype" 
                            (selectionChange)="changeOptions(item, $event.value)" 
                            class="choices">
                  <mat-option value="paragraph">
                    <span class="glyphicon glyphicon-align-justify choices "></span> Paragraph
                  </mat-option>
                  <mat-option value="multiplechoice">
                    <span class="glyphicon glyphicon-record choices"></span> Multiple choice
                  </mat-option>
                  <mat-option value="checkboxes">
                    <span class="glyphicon glyphicon-check choices"></span> Checkboxes
                  </mat-option>
                  <mat-option value="linearscale">
                    <span class="glyphicon glyphicon-option-horizontal choices"></span> Linear scale
                  </mat-option>
                  <mat-option value="date">
                    <span class="glyphicon glyphicon-calendar choices"></span> Date
                  </mat-option>
                </mat-select>
              </mat-form-field>
              <!-- 修复复制按钮的标签,改为正确的img标签 -->
              <img src="assets/img/dublicate@3x.png" class="dublicate" (click)="cloneTemplate()" />
            </div>
          </div>
        </div>
      </div>
    </div>
  </div>
</ng-template>

关键改动说明

  • 独立状态存储:用clonedQuestionItems数组保存每个克隆项的questiontype,每个项都有自己的状态副本,互不干扰。
  • 上下文传递:通过createEmbeddedView({ $implicit: item })把每个项的数据传递给模板,模板用let-item接收这个专属上下文。
  • 绑定到项的属性:所有依赖questiontype的地方(比如ngModel、*ngIf)都改成绑定到item.questiontype,而非组件的全局变量。

这样修改后,每个克隆的下拉菜单选择只会影响自己对应的项,不会再出现所有元素同步变化的问题。如果之后需要收集所有项的状态,直接遍历clonedQuestionItems数组即可。

内容的提问来源于stack exchange,提问作者Raj Rana

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.15 06:35:03