2
votes

I have an Angular 5 application with the library Kendo UI. In this one, I have a Grid with sorting and template for some header cells.

The sorting works but if I used template (with span inside) for a header cell, the sorting works just if we click beside the span.

This is my html code :

<kendo-grid
  #grid
  [kendoGridBinding]="getDataService().listOfSolution"
  [resizable]="false"
  [pageSize]="10"
  [pageable]="true"
  [sortable]="true"
  [filterable]="false"
  [groupable]="false"
  [reorderable]="false"
  [selectable]="false"
  [scrollable]="'none'"
  [rowClass]="rowCallback()"
  (detailCollapse)="onCollapse($event)"
  (detailExpand)="onExpand($event)"
  (sortChange)="onSort($event)"
  style="border: none;">
  <kendo-grid-column field="ThisOneWorks" title="ThisOneWorks"></kendo-grid-column>
  <kendo-grid-column-group title="Group" [locked]="false">
  <kendo-grid-column width="100px" field="pod.date" title="DATE" filter="date" [sortable]="true" [style]="{'min-width':'100px'}">
  <ng-template kendoGridHeaderTemplate>
  <span style="border-left:1px solid #E1E1E2;padding-left: 10px;">
      DATE
    </span>
  </ng-template>
  <ng-template kendoGridCellTemplate let-dataItem>
      <span style="border-left:1px solid #E1E1E2;padding-left: 10px;">
        {{ dataItem.pod.date | date : "MM/dd/yyyy" }}
      </span>
    </ng-template>
</kendo-grid-column>
...
</kendo-grid>

So, for the date, the sorting works only if we click beside the span.

How can I do to sort the column by clicking everywhere in the cell, also on the span ?

2

2 Answers

0
votes

I had to resort to re-creating the functionality in order to get the desired results. I hope that they add an in-built function that does this (or if they have one, I hope they add documentation for it). Here is what I have:

I have a variable which holds the sort descriptors, known as lineItemSort:

public lineItemSort: SortDescriptor[];

I hooked it to my grid:

<kendo-grid [sort]="lineItemSort" ...other params here>

I call my own sort function on click of the header template:

<ng-template kendoGridHeaderTemplate>
    <span (click)="lineItemManualSort('myFieldName')">My Field Name</span>
</ng-template>

And finally, I created my own function:

public lineItemManualSort(fieldName: string) {
    if (!this.lineItemSort) {
        this.lineItemSort = [];
    }

    let currentSortDescriptor;
    for (let sortDesc of this.lineItemSort) {
        if (sortDesc.field.toLowerCase() == fieldName.toLowerCase()) {
            currentSortDescriptor = sortDesc;
        }
    }

    //If sort does not exist, then add sort ascending
    if (currentSortDescriptor == null) {
        currentSortDescriptor = { dir: 'asc', field: fieldName };
        this.lineItemSort.push(currentSortDescriptor);
    } else {
        //If sort exists and asc, change it to desc
        if (currentSortDescriptor.dir == "asc") {
            currentSortDescriptor.dir = "desc";
        } else {
            //If sort exists desc, then remove it
            //Remove the current sort descriptor for the field
            let index = this.lineItemSort.indexOf(currentSortDescriptor);
            this.lineItemSort.splice(index, 1);
        }
    }
}

This function looks for the current field in the sort descriptors and does the following:

  • If no sort descriptor exists for the current field, it creates one with ascending order.
  • If a sort descriptor exists with ascending order, it switches the order to descending.
  • If a sort descriptor exists with descending order, it removes that sort descriptor.

This should mimic the in-built functionality of the grid. I have only tested this out with the sort mode being single, but it should work for multiple. If you (or anyone reading this) try it with sort mode as multiple, please comment and let us know if it works. I hope this helps!

0
votes

Problem

Per the Kendo forums:

The described behavior is caused by the fact that when sorting is enabled, and a header template is used, we do not handle the click events over the elements that are part of the template automatically, because the user might want to set up his own handlers and logic (for example - include a button in the header template).

This is why the click events of the header template elements have to be handled by the developer. In general, when sorting is enabled, the Grid header content is wrapped in an anchor tag ().

The solution described there (adapted to your code below) worked well for me since I didn't want to manually implement sort.

Caveat

Please note though that the author of this solution in the forums says that the parent anchor tag generally wraps the header content. It did for me. Not sure in which scenario it would not.

Solution

Given that the this is roughly what the generated HTML looks like:

<th>
    <a class="k-link"> <!-- presumably generated because sorting is enabled -->
        <span>Your Span</span>
        <span>Sorting Icon</span>
    </a>
</th>

In your component class add a special template click event that'll traverse up and click the anchor tag.

public onTemplateClick(e) {
    e.target.parentNode.click()
}

In your kendoGridHeaderTemplate call the click event as follows:

<ng-template kendoGridHeaderTemplate>
    <span (click)="onTemplateClick($event)" style="border-left:1px solid #E1E1E2;padding-left: 10px;">DATE</span>
</ng-template>