【问题标题】:Angular 5+ Form Loses ngmodel ValuesAngular 5+ 表单丢失 ngmodel 值
【发布时间】:2018-10-12 02:27:41
【问题描述】:

更新基于@Alexander Leonov 的回答。但是仍然有问题。

我有一个表单,当从另一个组件单击列表时会填充该表单。

通过 ngmodel 填充的表单由 form.ts 中的 currentTile 方法填充的空对象。但是,它似乎不喜欢我的数据结构。

currentTile 方法中,使用form.reset(t),填充title and description 字段,但sn-ps 不填充。

如您所见,使用当前结构(结构 A),sn-ps 驻留在分配给 code 属性的对象中:

  tile: Tile = {
    id: '',
    title: '',
    description: '',
    code: {snippetA: '', snippetB: '', snippetC: ''},
    isStockTile: null
  };

使用这种结构,如果我使用form.reset(t.code),那么表单将保留 sn-p 值,但当然不会保留 titledescription 值。

如果我将数据结构展平为(结构 B):

  tile: Tile = {
    id: '',
    title: '',
    description: '',
    snippetA: '', 
    snippetB: '', 
    snippetC: '',
    isStockTile: null
  };

然后使用form.reset(t),然后填充表单中的所有字段(当然,还要更改Tile 模型并相应地更新表单中的ngmodel 分配)。但是,我不需要更改我的数据结构。

这是结构 A 的所有设置方式。

列表组件:

@Component({
  selector: 'app-available-tiles',
  templateUrl: './available-tiles.component.html',
  styleUrls: ['./available-tiles.component.css']
})

export class AvailableTilesComponent implements OnInit {

  title = 'Available Tiles';
  tiles: Tile[];
  isEditing: Boolean = false;

  constructor(private tileService: TileService, private router: Router) { }

  ngOnInit() {}


  editTile(t: Tile) {
    this.tileService.tileSelected$.next(t);
    this.tileService.isNewTile$.next(false);
  }

}

列表视图:

<ul>
    <li *ngFor="let tile of tiles">
        <button *ngIf="isEditing && !tile.isStockTile" class="btn btn-info" (click) = "editTile(tile)">[...] {{ tile.title }} 
        </button>
    </li>
  </ul> 

表单组件:

@Component({
  selector: 'app-tile-editor',
  templateUrl: './tile-editor.component.html',
  styleUrls: ['./tile-editor.component.css']
})

export class TileEditorComponent implements OnInit {

  title = 'Tile Editor';
  showForm: boolean;

  @ViewChild ('theForm') form: any;

  // The object to hold info to and from the form.
  tile = {
    id: '',
    title: '',
    description: '',
    code: {snippetA: '', snippetB: '', snippetC: '' },
    isStockTile: null
  };

  constructor(private tileService: TileService, private router: Router) { }

  ngOnInit() {
     this.tileService.tileSelected$.subscribe(x => this.currentTile(x));
  }


   currentTile (t: Tile) {
     console.log('currentTile: ', t);
    this.showForm = true;
    this.isNewTile = false;
    // Need to reset form so dirty state can be reset.
    // Otherwise if a tile is being edited and another tile is loaded into the form prior to Update or Cancel,
    // the dirty state will still be applied.
    this.form.reset(t);
  }

表单视图:

   <form #theForm="ngForm">
    <label><input [(ngModel)]="tile.title" placeholder="Title" name="title" required #title="ngModel"></label> 
    <label><input [(ngModel)]="tile.description"  placeholder="Description" name="description" required #desc="ngModel"></label>
    <label><input [(ngModel)]="tile.code.snippetA"  placeholder="Snippet A" name="snippetA" required #snipA="ngModel"></label>
    <label><input [(ngModel)]="tile.code.snippetB"  placeholder="Snippet B (optional)" name="snippetB"></label>
    <label><input [(ngModel)]="tile.code.snippetC" placeholder="Snippet C (optional)" name="snippetC"></label>
    <button [disabled]="theForm.form.invalid || !title.dirty && !desc.dirty && !snipA.dirty" type="submit" (click)="updateTile()">Update</button>
</form>

【问题讨论】:

    标签: angular forms


    【解决方案1】:

    你只需要将新的 tile 直接传递到 form.reset() 中,如下所示:

    this.form.reset(t);
    

    【讨论】:

    • 根据您的回答更新了我的问题。
    【解决方案2】:

    特别感谢 @BlinkyBill 帮我解决这个问题。

    更新 @BlinkyBill 推测(我同意)form.reset() 可能没有提供深拷贝。 tile 对象包含一个对象,使用form.reset(t) 仅复制tile 对象的顶级属性,即tile.titletile.description 但是tile.code.snippetAform.reset(t) 上丢失了

    事实证明,只需使用 this.form.form.markAsPristine() 而不是 this.form.reset(t) 即可解决问题。

    部分形式.ts

    ngOnInit() {
        this.tileService.tileSelected$.subscribe(x => this.currentTile(x));
    }
    

    .subscribe 回调中:

       currentTile (t) {
            this.showForm = true;
            this.isNewTile = false;
            this.tile.id = t.id;
            this.tile.title = t.title;
            this.tile.description = t.description;
            this.tile.code.snippetA = t.code.snippetA;
            this.tile.code.snippetB = t.code.snippetB;
            this.tile.code.snippetC = t.code.snippetC;
            this.form.form.markAsPristine(); // Do not use form.reset() to reset dirty state
          }
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2018-02-17
      相关资源
      最近更新 更多