Angular 5+ Form失去了ngmodel值

时间:2018-05-02 03:43:27

标签: angular forms

根据@Alexander Leonov的回答

更新了。但仍有问题。

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

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

currentTile方法中,使用form.reset(t)title and description字段会填充,但代码段不会填充。

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

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

使用此结构,如果我使用form.reset(t.code),则表单将保留代码段值,但当然不会保留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>

2 个答案:

答案 0 :(得分:1)

你只需要将新的tile直接传递给form.reset(),就像这样:

this.form.reset(t);

答案 1 :(得分:0)

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

更新 @BlinkyBill推测(我同意)redux可能未提供深层复制。 form.reset()对象包含一个对象,并且仅使用tile复制form.reset(t)对象的顶级属性,即tiletile.title tile.descriptiontile.code.snippetA

上丢失了

只需使用form.reset(t)代替this.form.form.markAsPristine()即可解决问题。

Partial form.ts

this.form.reset(t)

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

.subscribe