Dragula 计算出排序顺序 - 如何禁用

Dragula Figures out sort order - how to disable

我正在使用 Dragula 来实现拖放功能。它一直有效,直到我从服务器端刷新我的列表:

this.columnList = newValue;

Dragula 似乎想像以前一样保留列表中的顺序,所以它弄乱了服务器端的排序顺序。 我不需要这个功能。 我已阅读文档、教程和示例,但找不到如何在 Dragula 中禁用自动排序。

我非常有信心没有自动排序,至少在默认情况下是这样。最小的独立示例是我们的朋友。好吧,不管网络可以使用更多示例,虽然很难证明是否定的,但我会证明在默认情况下没有自动排序,并尝试猜测问题出在哪里。

抱歉,我才意识到您使用的是纯 JS,并且可能使用 AngularJS 而不是 Angular2。不管怎样,下面的内容应该还是有点用的。

首先我们需要一个简单的代码库,让我们使用 Angular-CLI 来创建该库(https://www.npmjs.com/package/angular-cli): then follow 我们将拥有完全相同的起始库。

现在将 app.component.html 的内容替换为:

<div><button (click)="inOrderGreekAlphabet()">In Order Greek Alphabet</button></div>
<div><button (click)="reversedGreekAlphabet()">Reversed Greek Alphabet</button></div>
<div><button (click)="displyStateOfItems()">Display state of Items</button></div>
<div>
    <div class='wrapper'>
        <div class='container' [dragula]='"first-bag"'  [dragulaModel]="items">
            <div *ngFor="let item of items">{{item}}</div>
        </div>
    </div>
</div>

将app.component.ts的内容替换为:

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

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.css'],
    viewProviders: [DragulaService]
})
export class AppComponent {
    public items: string[];
    private GREEK_ALPHABET:string[] = ["alpha", "beta", "gamma", "delta", "epsilon", "zeta", "eta", "theta", "iota", "kappa", "lambda", "mu", "nu", "xi", "omicron", "pi", "rho", "sigma", "tau", "upsilon", "phi", "chi", "psi", "omega"];

    constructor() {
        this.inOrderGreekAlphabet();
    }

    public inOrderGreekAlphabet(){
        this.items = this.GREEK_ALPHABET.slice();
    }

    public reversedGreekAlphabet() {
        this.items = this.GREEK_ALPHABET.reverse();
    }

    public displyStateOfItems(){
        alert(JSON.stringify(this.items));
    }    
}

如果您 运行 上面的内容,您会发现模型与列表同步,如 显示项目状态 按钮所示。但是,如果我们从 app.component.html 中删除 [dragulaModel]="items",我们会发现模型不同步。不是德拉古拉多了,而是少了。


现在解决问题...

同步本地状态时,我们可以尝试以下几种方法:

首先请注意,虽然添加 [dragulaModel]="items" 确实使列表与数组同步,但我们仍然需要一个钩子来实现我们的自定义服务器同步代码,稍后会详细介绍。

如果我们忽略 dragula 框架并尝试为项目创建 getter setter。但是,如果我们将所有项目实例重命名为 _items,然后添加:

//This is to demonstrate an issue, this is NOT A Solution!
get items():string[]{
    console.log("call from getter: could do server sync here?");
    return this._items;
}

set items(i:string[]){
    console.log("call from setter: or perhaps here?");
    this._items = i;
}

但是上面的方法不会工作,或者更确切地说它可以工作但是查看控制台日志显示 setter 被调用一次,然后所有后续访问都是使用 getter 完成,并且 getter 在拖动过程中被多次调用,如果用户悬停并移动,可能会在几秒钟内生成数百次调用。此外,让用户知道页面是否需要保存可能会很好,在可能无限的列表上进行数组比较,不确定的次数听起来不是一个好主意,虽然可能有 可以 解决此 dragula 的纯 Java/TypeScript 解决方案提供了一种在项目被删除时仅进行一次检查的方法。

添加以下代码,替换构造函数,并删除 setter/getter 因为这是一个愚蠢的想法(我们真的只对 drop 部分感兴趣,但完整性永远不会受到伤害):

constructor(private dragulaService: DragulaService) {
    dragulaService.drag.subscribe((value) => {
        console.log(`drag: ${value[0]}`);
        this.onDrag(value.slice(1));
    });
    dragulaService.drop.subscribe((value) => {
        console.log(`drop: ${value[0]}`);
        this.onDrop(value.slice(1));
    });
    dragulaService.over.subscribe((value) => {
        console.log(`over: ${value[0]}`);
        this.onOver(value.slice(1));
    });
    dragulaService.out.subscribe((value) => {
        console.log(`out: ${value[0]}`);
        this.onOut(value.slice(1));
    });
    this.inOrderGreekAlphabet();
}

private onDrag(args) {
    let [e, el] = args;
    //do something
}

private onDrop(args) {
    let [e, el] = args;
    // do something
}

private onOver(args) {
    let [e, el, container] = args;
    // do something
}

private onOut(args) {
    let [e, el, container] = args;
    // do something
}

以上内容取自 https://github.com/valor-software/ng2-dragula#events and provides the ability to manually implement the synchronization without the use of the dragulaModel directive but we can also build on that directive as the next section of the documentation shows (https://github.com/valor-software/ng2-dragula#special-events-for-ng2-dragula),因此我们不需要执行上述操作,最低限度只需要(并且我们 必须 在这种情况下使用 dragulaModel 指令):

constructor(private dragulaService: DragulaService) {
    dragulaService.dropModel.subscribe((value) => {
        console.log(`dropModel: ${value[0]}`);
        this.onDropModel(value);
    });
    this.inOrderGreekAlphabet();
}

private onDropModel(args){
    let [bagName, el, target, source] = args;
    //do something, such as sync items with the server.
    //or setting a flag to indicate if items is different from when it was last saved
}

你应该有一个很好的工作解决方案。