2016-12-07 5 views
8

Arbeiten mit ng2-Dragula. Ich freue mich, die orderNumber für jedes Element in einer Datenbank mithilfe der neuen abgelegten Reihenfolge zu aktualisieren.Angular 2 Dragula Modell falsch aktualisiert

Die neue Modellreihenfolge, die zurückgegeben wird, spiegelt nicht die Reihenfolge in der Tasche wider.

TL; DR: hat jemand Neuordnung in einer Datenbank onDrop mit ng2-dragula implementiert?

+0

das gleiche Problem zu haben und kann nicht scheinen, eine Antwort zu finden. Ich verliere tatsächlich das DOM-Element, das ich komplett ziehe, sobald ich es fallen lasse. Das Entfernen des '[DragulaModel] = 'myList'' scheint dieses seltsame Verhalten zu beheben (immer noch Drag & Drop möglich - kann aber den Aufruf von dragulaService.dropModel nicht mehr auslösen). –

+0

@DanJ, ​​sehe ich nur ein Setup-Szenario, nichts über onDrop oder das Modell von onDrop zurückgegeben? –

+0

Entschuldigung, muss ein Kopierproblem sein - im Kreis herumlaufen und versuchen, das Problem herauszufinden. –

Antwort

5

Wenn Sie möchten in der Lage sein, Objekte zu ziehen (ohne sie verschwinden) und die dropModel Ereignis ausgelöst:

  • Setzen Sie den [dragula] und [dragulaModel] Richtlinien im Elternelement. (Zum Beispiel, im Gegensatz zu dem aktuellen doc, wo es heißt, sie setzt in den <li>, müssen Sie sie in den <ul>

  • Injizieren Sie die dragularService setzen, und im Konstruktor Ihrer Komponente:

  • rufen Sie die dragulaService.setOptions für den Beutel (ein leeres Wörterbuch passieren kann). Wenn Sie es nicht nennen, wird dropModel Rückruf nicht gefeuert

  • abonnieren dropModel

Das Ergebnis:

<!--thecomponent.html--> 
<h2>Playlists</h2> 
<ul [dragula]='"first-bag"' [dragulaModel]='playlists'> 
    <li *ngFor="let playlist of playlists"> 

//Inside the component.ts 
playlists: Playlist[]; 

constructor(private youtubeService: YoutubeService, private dragulaService: DragulaService) { 

    dragulaService.setOptions('first-bag', {}) 
    dragulaService.dropModel.subscribe((value) => { 
     this.onDropModel(value); 
    }); 
} 

private onDropModel(args) { 
    //Here, this.playlists contains the elements reordered 
} 
+1

danke, aber ich bin zu diesem Zeitpunkt gekommen - mein Problem ist das Objektmodell von OnDrop ist in der falschen Reihenfolge. Ich bin ziemlich sicher, dass es eine Einschränkung der Bibliothek ist, da das abgelegte Objekt in den richtigen Index verschoben wird, aber die anderen nur nach unten verschoben werden, anstatt neu zu sortieren. Dies wäre sehr nützlich, um herauszufinden, in welchen Slot der neue ging, aber ich muss die Bestellnummer jedes ** Artikels in der Liste ersetzen. –

+0

Hier ist eine gute Diskussion, die anderen helfen könnte und enthält auch einen Link zu einem Plunk, der zeigt Sortieren von Elementen mithilfe von dropModel und Erfassen der richtigen Reihenfolge, nachdem ein dropModel-Ereignis ausgelöst wurde. https://github.com/valor-software/ng2-dragula/issues/306 – rmcsharry

2

ich endlich eine Lösung gefunden. Ich habe eine horizontale Liste. Die ersten beiden Elemente sind diejenigen, die ich ignorieren möchte und alle haben die CSS-Klasse ignore. Und alle Elemente haben die item Klasse. So Markup:

<ul [dragula]='"foo-list"' class="list"> 
    <li class="list ignore">a</li> 
    <li class="list ignore">b</li> 
    <li class="list" *ngFor="let item of getList()" [attr.data-id]="item.id">{{ item.name }}</li> 
</ul> 

Dann wird das Typoskript:

constructor(private dragulaService: DragulaService) { 
    let dragIndex: number, dropIndex: number; 

    dragulaService.setOptions('foo-list', { 
     moves: (el, source, handle, sibling) => !el.classList.contains('ignore'), 
     accepts: (el, target, source, sibling) => sibling === null || !sibling.classList.contains('ignore'), 
     direction: 'horizontal' 
    }); 

    dragulaService.drag.subscribe((value) => { 
     // HACK 
     let id = Number(value[1].dataset.id); 
     if (!!id) { 
      dragIndex = _.findIndex(this.getList(), {id: id}); 
     } 
    }); 

    dragulaService.drop.subscribe((value:any[]) => { 
     // HACK 
     let elementNode = value[2].querySelectorAll('.item:not(.ignore)').item(dragIndex); 
     if (elementNode) { 
      let id = Number(elementNode.dataset.id); 
      if (!!id) { 
       dropIndex = _.findIndex(this.getList(), {id: id}); 
      } 
     } 

     if (value[2] === value[3]) { // target === source 
      if (dragIndex >= 0 && dropIndex >= 0 && dragIndex !== dropIndex) { 
       let temp: any = this.list[dragIndex]; 

       this.list[dragIndex] = this.list[dropIndex]; 
       this.list[dropIndex] = temp; 
      } 
     } 

     // Custom code here 
    }); 
} 

getList(): any[] { 
    return this.list; 
} 
1

I Marçal Antwort unglaublich hilfreich, und haben sogar erweitert auf sie ein wenig, ein Update zu meinem DB schreiben mit der Sequenz Wert jedes zu aktualisieren Artikel (Kontakte in einer Organisation, in meinem Fall) in der Liste:

HTML (Container ist die Organisation des Kontakts.ein Kontakt, in meinem Fall, kann nicht zwischen Organisationen) bewegt werden:

<div class="container" [dragula]="'org-' + org.id" [dragulaModel]="org.contacts"> 
    <nested-contact *ngFor="let contact of org.contacts" [user]="contact" class="contact" [attr.data-id]="contact.id"></nested-contact> 
</div> 

JS (in meinem Kontakt Service, eine PUT-Funktion zur Aktualisierung der gespeicherten Sequenzwerte, die mit jedem meiner Kontakten, so dass ihre Aufträge bestehen):

contactsIdPut (id, body) { 
    let url = '/api/v3/contacts/' + id + '?access_token=' + localStorage.getItem('access_token'); 
    let headers = new Headers({ 'Content-Type': 'application/json' }); 
    let options = new RequestOptions({ headers: headers }); 

    return this.http.put(url, body, options) 
    .map((response: Response) => { 
     return response.json(); 
    }); 

}

JS (in meiner Organisation view-Komponente, die Aktionen auf Drag & Drop gezogen werden zu umreißen, respectively):

export class nestedOrganizationComponent { 
    orgs = []; 
    thisOrg: any; 
    thisContact: any; 

    constructor (private _contactService: ContactService, private dragulaService: DragulaService) { 
    this._contactService = _contactService; 

    let dragIndex: any; 
    let dropIndex: any; 
    let elementNode: any; 

    dragulaService.drag.subscribe((value) => { 
     let id = Number(value[1].dataset.id); 
     let orgId: Number = value[0].split('-')[1]; 
     elementNode = value[2].querySelectorAll('.contact:not(.ignore)').item(dragIndex); 

     if (!!id) { 
     // this renderedOrgs is just an array to hold the org options that render in this particular view 
     this._organizationService.renderedOrgs.push(this.org); 
     this.thisOrg = this._organizationService.renderedOrgs.filter(org => { return org.id == orgId; })[0]; 
     this.thisContact = this.thisOrg.contacts.filter(contact => { return contact.id == id; })[0]; 

     let arr = this.thisOrg.contacts.map(x => { return x.id; }); 
     dragIndex = arr.indexOf(id); 
     } 
    }); 

    dragulaService.drop.subscribe((value: any[]) => { 
     if (elementNode) { 
      let id = Number(elementNode.dataset.id); 
      if (!!id) { 
      let arr = this.thisOrg.contacts.map(x => { return x.id; }); 
      dropIndex = arr.indexOf(id); 
      } 
     } 

     if (value[2] === value[3]) { // target container === source container 
      if (dragIndex >= 0 && dropIndex >= 0 && dragIndex !== dropIndex) { 
      this.thisOrg.contacts.forEach((contact, index) => { 
       contact.sequence = index; 
       this.updateSequence(contact.id, index); 
      }); 
      } 
     } 
    }); 
    } 

    updateSequence (id: Number, index: Number) { 
    let contactBody = { 
     avatar: { 
     sequence: index, 
     } 
    }; 

    return this._contactService.contactsIdPut(id, contactBody) 
     .subscribe(
     (data: any) => { 
      // nothing is needed, the same view can apply because the contact has already been moved. 
     }, 
     (error: any) => { 
      console.error(error); 
     } 
    ); 
    } 
} 

Hoffentlich gibt dies ein bisschen mehr Klarheit in Bezug auf die Angelegenheit an jemand anderen an einem Ort, der ähnlich ist, wo ich mich heute befand.

3

Ich benutzte die ng2-Dragula und es ist ziemlich seltsam auf etwas, das ich bemerkt habe. Das Problem, das ich hatte, war das gleiche. Der Serveraufruf aktualisiert das Datenobjekt nicht entsprechend der gezogenen Reihenfolge.

Ich habe gerade If-Klausel innerhalb der ngDoCheck Lifecycle-Hook verwendet, um das Problem zu lösen.

Es ist in dem gedruckten Objekt in der Konsole sortiert. Nach einem tieferen Graben könnte ein Bit im Netzwerk herausfinden, dass das Objekt, das mit dem Update-Server-Aufruf gesendet wurde, nicht aktualisiert wurde.

Also, weil der Serveraufruf erfolgt, bevor das Datenobjekt aktualisiert wird.

Alles, was ich getan habe, war das Hinzufügen einer globalen Variablen, die verfolgen können, ziehen das Datenobjekt aktualisiert hat.

private dropModelUpdated = false; 

ngAfterViewInit() { 
    // this method only changes a variable to execute a method in ngDoCheck 
    this.dragulaService.drop.subscribe((value) => { 
     this.dropModelUpdated = true; 
    }); 
} 

, dann im ngDoCheck Lifecycle Haken,

ngDoCheck() {  
    if (this.dropModelUpdated) { // this excutes if this.dropModelUpdated is true only 
     const drake = this.dragulaService.find('any_bag_name').drake; 
     const models = drake.models; 
     this.modelContent.groups = models[0]; 
     // ...Here... Make the server or DB call to update the model with the changed/sorted order 
     this.dropModelUpdated = false; // make sure this is there for the next smooth execution 
    } 
} 
Verwandte Themen