Using Angular2+ pipes with Dragula on an array

放肆的年华 提交于 2019-12-12 04:13:56

问题


I have a Trello-like web app. with Tasks that can be dragged & dropped in status boxes (To do, ogoing and done). I use ng2-dragula to achieve the drag & drop feature and wanted to implement a way to filter my tasks with an Angular 2 pipe.

So I did, by first defining my pipe:

@Pipe({
  name: 'taskFilter',
  pure: false
})
export class TaskFilterPipe implements PipeTransform {
  transform(items: Task[], filter: Task): Task[] {
    if (!items || !filter) {
      return items;
    }
    // pipes items array, items which match and return true will be kept, false will be filtered out
    return items.filter((item: Task) => this.applyFilter(item, filter));
  }

  applyFilter(task: Task, filter: Task): boolean {        
    for (const field in filter) {
      if (filter[field]) {
        if (typeof filter[field] === 'string') {
          if (task[field].toLowerCase().indexOf(filter[field].toLowerCase()) === -1) {
            return false;
          }
        }
      }
    }
    return true;
  }
}

And adding it to my *ngFor:

<!-- For every different status we have, display a card with its tasks -->
<md-grid-tile *ngFor="let istatus of status">

    <!-- Display every task in our array and pipe in the filter -->
    <div *ngFor="let task of tasks | taskFilter:projectService.filteredTask">

        <!-- Check if said task has the right status and display it -->
        <md-card class="task-card" *ngIf="task.status == istatus" (click)="openDetails(task)">
            {{task.title}}
        </md-card>
    </div>
</md-grid-tile>

It works, yay ! But when I drag & drop any task, it simply disappears, never to be found again.

It seems that changing a task's status in any way is making it disappear, how can that be related to my pipe?

Is there a way to use both dragula and Angular 2 pipes?


回答1:


It's not because of your pipe. I faced this problem and it's CSS related.

Put this into a global style sheet (and of course, style it to your needs) :

// Dragula styling for the drag n' drop
.gu-mirror {
  font-weight: 500;
  padding: 8px;
  cursor: grabbing;
  position: fixed;
  margin: 0;
  z-index: 9999;
  opacity: .8;
  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=80)";
  filter: alpha(opacity=80)
}

.gu-hide {
  display: none!important
}

.gu-unselectable {
  -webkit-user-select: none!important;
  -moz-user-select: none!important;
  -ms-user-select: none!important;
  user-select: none!important
}

.gu-transit {
  opacity: .2;
  -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=20)";
  filter: alpha(opacity=20)
}



回答2:


In order for your pipe to work, you need to declare 'dragulaModels' on your dragula bags elements. The way you do it now, on drag&drop you only move your generated div into DOM without updating your model, thus your pipe will never work since your array of task never get updated on drop.

Here is a working example to give you guidance:

html

<div [dragula]='"first-bag"' [dragulaModel]="groupA.items">
  <div *ngFor='let item of groupA.items | filter:"C"' [innerHtml]='item.name'></div>
</div>
<div [dragula]='"first-bag"' [dragulaModel]="groupB.items">
  <div *ngFor='let item of groupB.items' [innerHtml]='item.name'></div>
</div>

component

import { Component } from '@angular/core';
import { dragula, DragulaService } from 'ng2-dragula/ng2-dragula';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {

  groupA: any = {
    name: 'Group A',
    items: [{ name: 'Item A' }, { name: 'Item B' }, { name: 'Item C' }, { name: 'Item D' }]
  };

  groupB: any = {
    name: 'Group B',
    items: [{ name: 'Item 1' }, { name: 'Item 2C' }, { name: 'Item 3' }, { name: 'Item 4' }]
  };

}

pipe

import { Pipe, PipeTransform } from '@angular/core';

@Pipe({
  name: 'filter',
  pure: false
})
export class FilterPipe implements PipeTransform {

  transform(items: Array<any>, filter: string): any {
    if (!items || !filter) {
      return items;
    }
    return items.filter(item => {
      for (const field in item) {
        if (item[field] === null || item[field] === undefined) {
          continue;
        }
        if (item[field].toString().toLowerCase().indexOf(filter.toLowerCase()) !== -1) {
          return true;
        }
      }
      return false;
    }
    );
  }
}

When you drag&drop elements from groupB to groupA, it will move your elements from one array to the other and filter your first array (in this case you will only display the items containing a 'c' on the first array).

Added a demo app Angular2+-demo-app-dragula-pipe




回答3:


You are missing your binding between display and business logic from the piece of code you posted. Dragula needs to know what needs to be updated after you drag anything. [dragulaModel] is pointing to your array, [dragula] to the name of your bag/ drake.

<md-grid-tile *ngFor="let istatus of status" [dragula]="'task-bag'" [dragulaModel]="tasks">

See docu: https://github.com/valor-software/ng2-dragula



来源:https://stackoverflow.com/questions/44820056/using-angular2-pipes-with-dragula-on-an-array

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!