web-dev-qa-db-ja.com

Angular 4-オブザーバブルから配列に新しいアイテムをプッシュする

locationsのリストを表示するページがあり、それぞれをクリックすると、assetslocationが表示されます。私はこのようにテンプレートを設定しました:

<li
    *ngFor="let location of locations"
    (click)="select(location)"
    droppable
    [dragOverClass]="'drag-target-border'"
    (onDrop)="onItemDrop($event, location)"
    >
      {{ location.name }}
      <ul *ngIf="currentLocation == location && assetsVisible">
        <ng-container *ngIf="currentLocation.assets?.length > 0;else message">
          <li
            *ngFor="let asset of currentLocation.assets"
            class="asset"
            draggable
            [dragData]="asset"
            >
            <p>{{ asset.title }}</p>
            <p>{{ asset.address }}</p>
            <p>{{ asset.value }}</p>
          </li>
        </ng-container>
        <ng-template #message>No assets for {{ location.name }}</ng-template>
      </ul>
  </li>

そしてコンポーネントでは、空のassets配列と空のcurrentLocationを設定しました:

  locations: any[] = [];
  currentLocation: any = {};
  assets: any[] = [];

そして、メソッドselectで、次のようにアセットをフェッチしています:

  select(location:any = {){

    if (this.currentLocation != location || !this.assetsVisible) {
      this.assetsVisible = true;
    }
    else {
      this.assetsVisible = false;
    }

    this.currentAddress = address;

    this.locationService.getAssets(location.Id)
      .subscribe(
        assets => this.assets = assets
      );
  }

Angularのドラッグアンドドロッププラグイン を使用しているため、ユーザーがアセットをある場所から別の場所にドラッグできるようにしたいと思います。そして、そのアセットを配列assetsに一時的にプッシュします。そのための関数を作成しました。

onItemDrop(e: any, location:any = {}) {
   this.assets = [];
   this.assets.Push(e.dragData);        
   this.select(location);
}

したがって、ユーザーがある場所から別の場所にアセットをドラッグアンドドロップすると、assets配列が空になり、配列にドラッグされた新しいアセットがプッシュされます。しかし、selectメソッドで、assetsがドロップされた新しいlocationのすべてのassetを取得し、assets配列を書き換えます。これらのassetsを同じ配列にプッシュして、新しいassetを追加し、そのassetslocationをサービスエンドポイントから取得する方法を教えてください。私は別のアプローチも試しましたが、最初に配列アセットを空にしてから、新しいlocationと新しいassetを呼び出してselectメソッドに渡しました。

onItemDrop(e: any, location:any = {}) {
    this.assets = [];
    this.select(location, e.dragData);
  }

次に、selectメソッドでassetパラメータをオプションとして設定し、サービスからassetsのすべてのassetsを取得した後、location配列にプッシュしました。

select(location:any = {}, asset?:any = {}) {


    this.locationService.getAssets(location.Id)
      .subscribe(
        assets => this.assets = assets,
        if (asset) {this.assets.Push(asset)} 
      );
  }

しかし、それは機能しませんでした。新しい場所にドロップされたアセットはテンプレートに表示されませんでした。どうすればそれを達成できますか?

5
Leff

最初のアプローチでは、assets関数のsubscribe配列を上書きしています。

_this.locationService.getAssets(location.Id).subscribe(
    assets => this.assets = assets
);
_

したがって、明らかに、その配列に一時的に保存したassetは、この時点で失われます。

2番目のアプローチはより理にかなっていますが、この例ではsubscribeを間違って使用しています。

_this.locationService.getAssets(location.Id).subscribe(
    assets => this.assets = assets,
    if (asset) {this.assets.Push(asset)} 
);
_

この場合、if (asset) ...部分は、2番目の引数として_error callback_であるsubscribe呼び出しに渡されます。あなたはこのようにしたいです:

_this.locationService.getAssets(location.Id).subscribe( (assets) => {
    this.assets = assets;
    if (asset) {
         this.assets.Push(asset)
    } 
});
_

それが役に立てば幸い。

更新:if (asset) ...の部分、つまり実装方法がエラーコールバックとして機能しているかどうかさえわかりません。式ではなく関数が予期されているためにコールバックが呼び出されると、おそらくエラーが発生します(ただし、先ほど述べたように、それについてはわかりません)。

2
lexith