Rad*_*Zec 8 javascript drag-and-drop dragula angular-dragula
我正在使用Dragula进行拖放功能.它一直有效,直到我从服务器端刷新列表:
this.columnList = newValue;
Run Code Online (Sandbox Code Playgroud)
它接缝,Dragula想要像以前一样保留列表中的顺序,所以它搞乱了服务器端排序顺序.我不需要这个功能.我已阅读文档,教程,示例,但无法找到如何在Dragula中禁用自动排序.
我非常有信心没有自动排序,至少在默认情况下是这样.最小的自包含的例子是我们的朋友.好吧,无论网络可以使用更多的例子,虽然很难证明是负面的,但我会证明在默认情况下没有自动排序,并试图猜测问题所在.
很抱歉只有在我意识到你使用纯JS并且可能使用AngularJS而不是Angular2之后.无论如何仍然有些有用.
首先我们需要一个简单的代码库,让我们使用Angular-CLI创建基础(https://www.npmjs.com/package/angular-cli):然后按照如何使用ng2-dragula设置angular-quickstart,我们将具有完全相同的起始基础.
现在用以下内容替换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>
Run Code Online (Sandbox Code Playgroud)
用以下内容替换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));
}
}
Run Code Online (Sandbox Code Playgroud)
如果运行上述操作,您将发现模型与列表同步,如" 显示项目状态"按钮所示.但是,如果我们[dragulaModel]="items"从app.component.html中删除,我们会发现该模型未同步.并不是说拉古拉正在做一些额外的事情,它实际上是在做更少的事情.
现在解决这个问题......
在同步本地状态时,我们可以尝试以下几种方式:
首先请注意,虽然添加[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;
}
Run Code Online (Sandbox Code Playgroud)
但是上面的方法不行,或者说它可以正常工作,但是查看控制台日志会显示setter被调用一次,然后所有后续访问都使用getter完成,并且在拖动过程中多次调用getter,如果用户可以在几秒钟内生成并移动大约数百个呼叫.此外,让用户知道是否需要保存页面,在可能无限制的列表上进行数组比较,不确定的次数听起来不是一个好主意,并且可能存在可以解决此拖拽问题的纯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
}
Run Code Online (Sandbox Code Playgroud)
以上内容取自https://github.com/valor-software/ng2-dragula#events,并提供了在不使用dragulaModel指令的情况下手动实现同步的功能,但我们也可以在下一部分的基础上构建该指令.文档显示(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
}
Run Code Online (Sandbox Code Playgroud)
你应该有一个很好的工作解决方案.