Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 4 - pushing a new item to an array from an observable

I have a page where I display a list with locations, and clicking on each of them I am displaying assets for that location. I have set up the template like this:

<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>

And in the component, I have set the empty assets array, and an empty currentLocation:

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

And then in the method select I am fetching the assets like this:

  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
      );
  }

What I would like to do is to since I am using the drag and drop plugin for Angular I would like to make it possible for user to drag assets from one location to another. And then just temporarily push that asset to an array assets. I have made a function for that:

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

So, when a user drags and drops the asset from one location to another, I am emptying the assets array, and pushing the new asset that was dragged to the array. But, then in the select method I am getting all the assets for that new location that the asset was dropped to, and that rewrites the assets array. How can I push to the same array those assets, so that I have both the new asset added and the assets of that location that I get from the service endpoint? I have tried another approach as well, where I was first emptying array assets, and then calling and passing new location and new asset to select method:

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

And then, in the select method I have set the asset parameter as optional, and then pushing it there to the assets array after I got all the assets for that location from the service:

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


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

But, that didn't work, the asset dropped to new location wasn't displayed in the template. How can I achieve that?

like image 978
Leff Avatar asked Oct 29 '22 06:10

Leff


1 Answers

Well in your first approach, you're overwriting your assets array in your subscribe function:

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

So obviously, the asset you temporarily saved in that array is lost at this point.

Your second approach makes more sense, but you're using subscribe wrong in this example:

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

In this case the if (asset) ... part is passed as the second argument to your subscribe call which is the error callback. You want to do it like this:

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

Hope it helps.

Update: I'm not even sure if that if (asset) ... part, the way you implemented it, is even working as error callback. you probably get an error there if that callback is called because a function is expected, not an expression (but as i said, i'm not sure about that).

like image 57
malifa Avatar answered Nov 11 '22 12:11

malifa