2016-12-07 97 views
8

使用ng2-dragula。我正在使用新的删除订单更新数据库中每个项目的orderNumber。Angular 2 Dragula模型更新不正确

dragulaService.dropModel.subscribe((value) => { 
    var drake = dragulaService.find('bag-orders').drake 
    var models = drake.models 
    console.log(models) 
}) 

它返回的新型号订单不反映包内的订单。

TL; DR:有没有人使用ng2-dragula在Drop数据库中实现重新排序?

+0

有同样的问题,似乎无法找到答案。我实际上丢失了一旦我放弃它就完全拖动的DOM元素。简单地删除'[dragulaModel] ='myList'似乎可以修复这种奇怪的行为(仍然可以拖放 - 但不再可以触发dragulaService.dropModel调用)。 –

+0

@DanJ,我看到的只是一个设置场景,onDrop或从onDrop返回的模型没有任何关系? –

+0

对不起,一定是一个复制粘贴问题 - 绕圈试图找出问题。 –

回答

5

如果你希望能够拖动物品(没有他们消失)和火灾的dropModel事件:

  • 放入父元素的[dragula]和[dragulaModel]指令。 (例如,违背当前的doc在那里说:把他们在<li>,你必须把它们放在<ul>

  • 注入dragularService,并且,在组件的构造函数:

  • 呼吁袋dragulaService.setOptions(你可以传递一个空字典)。如果你不调用它,dropModel回调将不会触发

  • 订阅dropModel

结果:

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

谢谢,但我已经到了这个阶段 - 我的问题是由onDrop返回的对象模型是错误的顺序。我相当肯定这是对图书馆的限制,因为丢弃的对象移动到正确的索引,但其他的只向下移动,而不是重新排序。这对于找到新插入的插槽是非常有用的,但是我需要在列表中替换**每个**项目的orderNumber –

+0

这是一个很好的讨论,可以帮助其他人,并且还包含指向plunk的链接,显示在dropModel事件触发后使用dropModel对项目进行排序并捕获正确的顺序。 https://github.com/valor-software/ng2-dragula/issues/306 – rmcsharry

2

我终于找到了解决办法。 我有一个水平列表。前两个元素是我想要忽略的元素,它们都具有CSS类别ignore。所有元素都有item类。所以标记:

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

然后打字稿:

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

我发现马萨尔的回答令人难以置信的帮助,甚至扩大了它一点点地更新发布到我的数据库更新每个序列值项目(在我的情况下是一个组织内的联系人)在列表中:

HTML(容器是联系人的组织。一接触,于我而言,不能组织之间移动):

<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(在我的联系服务,PUT功能更新与每个我接触的相关联的存储序列值,从而使他们的订单坚持):

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(在我的组织视图组件,大纲在拖放将要采取的行动,分别):

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

希望这可以让我更清楚地知道这个问题,与其他地方的其他人相似。

3

我正在使用ng2-dragula,这在我注意到的东西上很奇怪。我遇到的问题是一样的。服务器调用不会根据拖动的订单更新数据对象。

我刚刚在ngDoCheck生命周期挂钩中使用if子句来解决问题。

它在控制台的打印对象中排序。在深入挖掘之后,可以在网络中发现与更新服务器调用一起发送的对象是未更新的对象。

所以,这是因为服务器调用是在数据对象更新之前完成的。

我所做的只是添加一个全局变量,它可以跟踪拖动已更新的数据对象。

private dropModelUpdated = false; 

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

然后,在ngDoCheck生命周期挂钩,

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