0

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?

Christopher
  • 1,712
  • 2
  • 21
  • 50

3 Answers3

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)
}
  • Why would that be a CSS problem? It does not seem to do anything. Changing a task's status in any way makes it disappear, I guess it's a problem with my pipe. – Christopher Jun 29 '17 at 08:39
  • Because when I faced the problem, I figured out that the CSS of the objects moving wasn't set. Thus, they didn't appeared to the user. I took the CSS of the demo website and styled it myself, and it worked. Did you put it in a global CSS file ? Not in your component file, I mean in a file that is referenced in your `styles` attribute of your `angular-cli.json` file –  Jun 29 '17 at 08:41
  • I did put it in my global CSS file. – Christopher Jun 29 '17 at 08:45
  • Well in this case I don't know what's happening. Try inspecting your elements when you move them along to find their class and see if my problem is actually your problem. Also, try without the pipe to see if it works. –  Jun 29 '17 at 08:50
  • I was having a similar but different problem with gu-mirror items not being visible. This helped me immensely ty. – acumartini Aug 01 '17 at 21:45
  • No problem dude, glad I could help –  Aug 02 '17 at 08:00
0

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

BogdanC
  • 2,746
  • 2
  • 24
  • 22
0

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

Zibelas
  • 302
  • 1
  • 12