Угловая форма 5+ теряет значения ngmodel - PullRequest
0 голосов
/ 02 мая 2018

Обновлено на основании ответа @Alexander Leonov. Тем не менее, все еще возникают проблемы.

У меня есть форма, которая заполняется при нажатии на список из другого компонента.

Форма, которая заполняется с помощью ngmodel пустого объекта, который заполняется методом currentTile в form.ts. Однако, мне не нравится моя структура данных.

В методе currentTile с использованием form.reset(t) поля title and description заполняются, а фрагменты - нет.

Как видите, с текущей структурой (структура A) фрагменты находятся в объекте, назначенном свойству code:

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

С этой структурой, если я использую form.reset(t.code), то форма будет сохранять значения фрагмента, но, конечно, значения title и description не сохраняются.

Если я выровняю свою структуру данных как (Структура B):

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

И используйте form.reset(t), после чего заполняются все поля в форме (также изменяя модель Tile и, соответственно, обновляя назначения ngmodel в форме). Однако мне не нужно менять структуру данных.

Вот как все настроено в структуре А.

Компонент листинга:

@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 голосов
/ 03 мая 2018

Особая благодарность @BlinkyBill за помощь в этом.

Обновление @BlinkyBill предположил (и я согласен), что form.reset(), возможно, не предоставил глубокую копию. Объект tile содержит объект и, используя form.reset(t), копирует только свойства верхнего уровня объекта tile, т.е. tile.title, tile.description, однако tile.code.snippetA теряется в form.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
      }
0 голосов
/ 02 мая 2018

Вам просто нужно передать новую плитку прямо в form.reset (), например:

this.form.reset(t);
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...