2017-01-03 11 views
1

私は1種類のオブジェクトを扱うアプリを持っている。私はサービスを使ってオブジェクトの状態を管理します。あるコンポーネントでは、オブジェクトを表示します。ここから、別のコンポーネントでフィールドをクリックして編集することができます。ボタンをクリックして、新しい項目をフィールドに追加したり、項目を削除したりすることもできます。角度2のテンプレートを更新するが、クリックハンドラを破る

ほとんどの場合、これは正常に機能しますが、エラーメッセージが表示されずに破損することがあります。削除または編集ボタンまたはフィールドをクリックしても何も起こりません。クリックハンドラーが壊れています(私はこれをコンソールでチェックしました)。これは、通常、配列を追加または削除した後に発生します。

要素を追加するときに、httpを使用してデータベースに保存されていることを確認してから、新しいドロップレットのオブザーバブルが返された後で、角度更新を行うようにしているので、そしてディスプレイは常に更新されます。しかし、ディスプレイが更新されることもありますが、Auguryは気付きませんが、これは非常に奇妙です。そこでヒントを追加します。たとえば、ヒントがデータベースに表示され、返され、ビューが更新されますが、Auguryはコンポーネント内でそのヒントを表示しません。

また、矛盾しています。ときどきうまくいくこともあります。

ここに、サンプルコードをいくつか示します。

<h4>Hints (optional)</h4> 
<button class="btn btn-sm" [routerLink]="['/create/create5']">Add New</button> 
<div *ngIf="droplet.hints.length < 1">None</div> 
<div class="row" *ngFor="let hint of droplet.hints; let i=index"> 
    <div class="hint col-md-10" (click)="selectHint(i)"> 
    <span [innerHTML]="hint.content || empty"></span> 
    <span (click)="removeElement(i, 'hint')" class="pull-right glyphicon glyphicon-remove" aria-hidden="true"></span> 
    </div> 
</div> 

<h4>Tags 
    <div class="progress-marker" [class.complete]="droplet.tags.length > 0"></div> 
    <div class="progress-marker" [class.complete]="droplet.tags.length > 1"></div> 
    <div class="progress-marker" [class.complete]="droplet.tags.length > 2"></div> 
</h4> 
<button class="btn btn-sm" [routerLink]="['/create/create6']">Add New</button> 
<div *ngIf="droplet.tags.length < 1">None</div> 
<br> 
<button *ngFor="let tag of droplet.tags; let i=index" type="button" class="btn btn-default btn-sm" (click)="removeElement(i, 'tag')"> 
    <span class="glyphicon glyphicon-remove" aria-hidden="true"></span> {{ tag.tag }} 
</button> 

このようなフィールドはいくつかありますが、一般的には* ngIfのフィールドが問題の原因となります。私が言ったように、配列の中の要素を追加したり削除したり編集したりすると、テンプレートは更新されますが、配列の中の何もこの後は機能しません。

関連するコンポーネントのコードは次のようになります。

import { Component, OnInit } from '@angular/core'; 
import { Droplet } from '../droplet'; 
import { DropletService } from '../droplet.service'; 
import { Router } from '@angular/router'; 
import { Subscription } from 'rxjs/Rx'; 
import { HttpService } from '../http.service'; 

export class ShowDropletComponent implements OnInit { 
    droplet: Droplet; 

    constructor(
    private dropletService: DropletService, 
    private router: Router, 
    private httpService: HttpService 
) { } 

    ngOnInit() { 
    this.droplet = this.dropletService.getCurrentDroplet(); 
    this.dropletService.pushedDroplet.subscribe(
     droplet => this.droplet = droplet 
    ) 
    } 

    //using dummy to ensure element not updated unless returned from server 
    removeElement(index, element) { 
    console.log("remove clicked"); 
    let dummy = this.droplet; 
    if (element === "explanation") { 
     this.router.navigate(['create/create3']); 
     dummy.explanations.splice(index, 1); 
    } else if (element === "question") { 
     this.router.navigate(['create/create4']); 
     dummy.questions.splice(index, 1); 
    } else if (element === "hint") { 
     this.router.navigate(['create/create5']); 
     dummy.hints.splice(index, 1); 
    } else if (element === "tag") { 
     dummy.tags.splice(index, 1); 
    } 
    this.httpService.saveDroplet(dummy) 
     .subscribe(
     (droplet: Droplet) => { 
      this.dropletService.updateCurrentDroplet(droplet); 
     } 
    ); 
    } 

    editThis(field) { 
    if (field === "description") { 
     this.router.navigate(['create/create2']); 
    } else if (field === "name") { 
     this.router.navigate(['create/create1']); 
    } 
    } 

    selectExplanation(index) { 
    console.log("select exp clicked"); 
    this.router.navigate(['create/create3', index]); 
    } 

    selectQuestion(index) { 
    console.log("rselect q clicked"); 
    this.router.navigate(['create/create4', index]); 
    } 

    selectHint(index) { 
    console.log("select hint clicked"); 
    this.router.navigate(['create/create5', index]); 
    } 

} 

私の推測では、それは* ngForビューで列を更新するが、どちらかのインデックスが正しく更新されていないか、またはクリックハンドラがあるとは何かということですテンプレートの特定の部分にある人だけではありません。私は迷っている。

答えて

1

*ngForディレクティブでアイテムを操作するときは、ユニークなインデックスを返す関数trackByを追加することが重要です。そのため、ディレクティブはアイテムの削除/追加時にそのプロパティを追跡できます。これに対する解決策は、奇数だった

<button *ngFor="let tag of droplet.tags; let i=index; trackBy: tag.tag" type="button"... 
+0

trackByを使用するときに関数を使用する必要があります。これは、各アイテムのIDを返します。しかし、悲しいことにそれは助けにはならない。私は同じ問題を経験しています。 – Finnjon

0

:あなたのtag.tagがあなたの代わりにこのようなあなたの*ngForを書くことができユニークであると仮定すると、

。私は左に表示されている編集フォームと右に編集または作成されているドロップレットを並べてコンポーネントを並べました。あなたは右のボタンやフィールドをクリックすることができ、それを編集するには適切なフォームが左側に表示されます。問題は、表示されているドロップレットが、左側のコンポーネントのすぐ下にあるフィールドを持っている場合、クリックがうまく行かず、ブラウザが単に画面の上部にスクロールするということでした。なぜこのようなことが起こったのか分かりませんが、同じビューポート内で強制的に問題を解決しました。

関連する問題