用于 Angular 行重新排序的 Kendo Grid - Angular 4/5 - HTML5 拖放 API

Posted

技术标签:

【中文标题】用于 Angular 行重新排序的 Kendo Grid - Angular 4/5 - HTML5 拖放 API【英文标题】:Kendo Grid for Angular Row Reordering - Angular 4/5 - HTML5 Drag and Drop API 【发布时间】:2018-06-15 19:41:58 【问题描述】:

我正在尝试实现具有行重新排序功能的 Kendo-Grid,如广告 here 所述。

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

下面是我的 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" >
            </kendo-grid-column>
            <kendo-grid-column field="title" title="To Do">
            </kendo-grid-column>
            <kendo-grid-column field="completed" title="Completed" >
                <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,但这也不起作用。

提前致谢!

【问题讨论】:

telerik.com/kendo-angular-ui/components/knowledge-base/… 【参考方案1】:

关键是您仅在通过AppComponent.dataStateChange() 调用更改state 时才调用AppComponent.handleDragAndDrop()。它发生在网格页面更改时,不会发生在数据初始化时。因此,快速修复将是

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。

【讨论】:

以上是关于用于 Angular 行重新排序的 Kendo Grid - Angular 4/5 - HTML5 拖放 API的主要内容,如果未能解决你的问题,请参考以下文章

Angular Kendo Grid:以编程方式选择行

如何在 Kendo Grid + Angular 4 中以编程方式设置选定行?

SSE 优化(行重新排序、操作整理)中的编译器(例如 g++)有多聪明

Angular Js 的 Kendo UI

Angular 的 Storybook 不显示由 Kendo UI 创建的元素

Kendo Ui Angular2 Grid 分页到第一页