用于角度行重新排序的Kendo网格 - Angular 4/5 - HTML5拖放API

时间:2018-01-06 00:10:10

标签: angular drag-and-drop kendo-grid rxjs kendo-ui-angular2

我正在尝试按行广告here实施具有行重新排序功能的Kendo-Grid。

当Grid处理通过Ajax调用获取的数据时,行的重新排序(即拖放行)在视图更改之前不起作用(例如:直到用户单击第2页在这个例子的分页中)

以下是我的app.component.ts文件

import { State, process } from '@progress/kendo-data-query';
import { Component, Renderer2, NgZone, AfterViewInit, OnInit, EventEmitter, OnDestroy } from '@angular/core';
import { Observable } from 'rxjs/Observable';
import 'rxjs/add/observable/fromEvent';
import { Subscription } from 'rxjs/Subscription';
import { HttpClient, HttpParams} from '@angular/common/http';

@Component({
    selector: 'my-app',
    template: `
        <kendo-grid
            [data]="gridData"
            [height]="410"
            [pageable]="true"
            [skip]="state.skip"
            [pageSize]="state.take"
            (dataStateChange)="dataStateChange($event)">
            <kendo-grid-column field="id" title="ID" width="60">
            </kendo-grid-column>
            <kendo-grid-column field="title" title="To Do">
            </kendo-grid-column>
            <kendo-grid-column field="completed" title="Completed" width="60">
                <ng-template kendoGridCellTemplate let-dataItem>
                    <input type="checkbox" [checked]="dataItem.completed" disabled/>
                </ng-template>
            </kendo-grid-column>
        </kendo-grid>
    `
})
export class AppComponent implements OnInit, AfterViewInit, OnDestroy {
    userData: any[] = []
    public state: State = {
        skip: 0,
        take: 10
    };
    public gridData: any = process(this.userData, this.state);
    private currentSubscription: Subscription;

    constructor(private renderer: Renderer2, private zone: NgZone, private _http: HttpClient) {}

    ngOnInit() {
      this.getUserData();  
    }

    public ngAfterViewInit(): void {
        this.currentSubscription = this.handleDragAndDrop();
    }

    public ngOnDestroy(): void {
        this.currentSubscription.unsubscribe();
    }

    public dataStateChange(state: State): void {
        this.state = state;
        this.gridData = process(this.userData, this.state);
        this.currentSubscription.unsubscribe();
        this.zone.onStable
            .take(1)
            .subscribe(() => this.currentSubscription = this.handleDragAndDrop());
    }

    private handleDragAndDrop(): Subscription {
        const sub = new Subscription(() => {});
        let draggedItemIndex;

        document.querySelectorAll('.k-grid-content tr')
        .forEach(item => {
            this.renderer.setAttribute(item, 'draggable', true);
            const dragStart = Observable.fromEvent(item, 'dragstart');
            const dragOver = Observable.fromEvent(item, 'dragover');
            const drop = Observable.fromEvent(item, 'drop');

            sub.add(dragStart.subscribe(({target}) => {
                draggedItemIndex = target.rowIndex;
            }));

            sub.add(dragOver.subscribe((e: any) => e.preventDefault()));

            sub.add(drop.subscribe((e: any) => {
                e.preventDefault();
                const dataItem = this.gridData.data.splice(draggedItemIndex, 1)[0];
                const dropIndex = e.target.closest('tr').rowIndex;
                this.zone.run(() =>
                    this.gridData.data.splice(dropIndex, 0, dataItem)
                );
            }));
        });

        return sub;
    }

  getUserData() {
    return this._http.get('https://jsonplaceholder.typicode.com/todos')
    .subscribe((fetchedData) => {
      this.userData = fetchedData;
      console.log(this.userData);
      this.gridData = process(this.userData, this.state);
      this.currentSubscription.unsubscribe();
      this.currentSubscription = this.handleDragAndDrop();
    });
  }
}

以下是app.module.ts文件

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { FormsModule } from '@angular/forms';
import { GridModule } from '@progress/kendo-angular-grid';
import { HttpClientModule } from '@angular/common/http';

import { AppComponent } from './app.component';

@NgModule({
  imports: [ BrowserModule, BrowserAnimationsModule, GridModule, FormsModule, HttpClientModule],
  declarations: [ AppComponent ],
  bootstrap: [ AppComponent ]
})

export class AppModule { }

Plunker Here

注意:我已尝试在我的Ajax数据调用中重新订阅handleDragAndDropevent,但这也不起作用。

提前致谢!

1 个答案:

答案 0 :(得分:2)

关键是,只有在通过AppComponent.handleDragAndDrop()电话更改state时才会呼叫AppComponent.dataStateChange()。它发生在网格页面更改上,并且不会在数据初始化时发生。所以,快速修复将是

getUserData() {
    return this._http.get('https://jsonplaceholder.typicode.com/todos')
    .subscribe((fetchedData) => {
      this.userData = fetchedData;
      console.log(this.userData);
      this.dataStateChange(this.state); // force state change, encapsulate process() call
    });
  }

固定的Plunker是here