Skip to content

Instantly share code, notes, and snippets.

@davidpurkiss
Created October 8, 2015 07:55
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save davidpurkiss/12a40e8f60094e4de574 to your computer and use it in GitHub Desktop.
Save davidpurkiss/12a40e8f60094e4de574 to your computer and use it in GitHub Desktop.
Custom Element - Aurelia Kendo Grid
<template>
<require from='kendo-ui/styles/kendo.common-bootstrap.min.css'></require>
<require from='kendo-ui/styles/kendo.bootstrap.min.css'></require>
<div>
<content></content>
</div>
</template>
import {inject, processContent, customAttribute, bindable, sync, ViewCompiler, ViewSlot, Container, ViewResources, TargetInstruction} from 'aurelia-framework';
import { EventAggregator } from 'aurelia-event-aggregator';
import {Compiler} from '../kendo/compiler';
import * as kendoUi from 'kendo-ui';
@processContent((compiler, resources, element, instruction) => {
parseUserTemplate(element, resources, instruction);
return true;
})
@inject(Element, Compiler, EventAggregator, TargetInstruction)
export class KendoGrid {
element: HTMLElement;
widget: any;
columns: any[] = null;
model: any = null;
@bindable selectable: boolean;
@bindable filterable: boolean;
@bindable pageable: boolean;
@bindable sortable: boolean;
@bindable pageSize: number = 10;
@bindable page: number = 1;
@bindable selectedItem: any;
@bindable selectedItems: any[];
@bindable autoBind: boolean;
@bindable editable: boolean;
@bindable toolbar: any[];
@bindable refreshFlag: any;
@bindable read: any;
aggregator: EventAggregator;
compiler: Compiler;
dataSource: kendo.data.DataSource;
constructor(element, compiler, aggregator, targetInstruction) {
this.element = element;
this.compiler = compiler;
this.aggregator = aggregator;
kendo.culture("en-GB");
this.columns = targetInstruction.behaviorInstructions[0].kendoGridColumns;
this.model = targetInstruction.behaviorInstructions[0].kendoDataSourceModel;
}
bind(ctx) {
this["$parent"] = ctx;
// Post parse the templates in "columns"
this.columns.forEach(c => {
if (c.hasOwnProperty("template")) {
// If there's no template string it must be the first time we are visiting the columns
// Push the template string into a new property and wrap the string with a func to compile the template
if (!c.hasOwnProperty("templateString"))
c["templateString"] = c["template"];
c["template"] = (dataItem) => {
try {
var cellctx = { "$item": dataItem, "$parent": ctx };
return this.compiler.compile(c["templateString"], cellctx).fragment.innerHTML;
}
catch (ex) {
console.error(ex);
}
}
}
});
}
refreshFlagChanged() {
this.refresh();
}
selectedItemChanged() {
}
attached() {
// Create the datasource
this.dataSource = new kendoUi.data.DataSource({
serverFiltering: true,
serverSorting: true,
serverPaging: true,
page: this.page,
pageSize: this.pageSize,
schema: {
data: "data",
total: "total",
model: this.model
},
transport: {
read: (options) => {
// Check if we have a grid read setup
if (!this.read) {
console.warn("No read method provided to Kendo Grid");
options.error([]);
return;
}
// User can transform the kendo options
return Promise.resolve(this.read(options.data))
.then(e => {
return options.success(e);
})
.catch(e => {
return options.error([]);
});
}
}
});
// Create the widget
$(this.element).kendoGrid({
dataSource: this.dataSource,
columns: this.columns,
filterable: this.filterable,
pageable: this.pageable,
selectable: this.selectable,
sortable: this.sortable,
autoBind: this.autoBind,
editable: this.editable,
toolbar: this.toolbar,
// Row selection
change: (e) => {
var selectedRows = this.widget.select();
var selectedItems = Array.prototype.slice.call(selectedRows).map(row => {
return this.widget.dataItem(row);
});
this.selectedItem = selectedItems[0];
this.selectedItems = selectedItems;
}
});
this.widget = $(this.element).data("kendoGrid");
}
refresh() {
if (this.widget)
this.widget.dataSource.read();
}
detached() {
$(this.element).data("kendoGrid").destroy();
}
}
function parseUserTemplate(element, resources, instruction) {
// Pull all of the attributes off the kendo-grid-col element
var columns = Array.prototype.slice.call(element.querySelectorAll("kendo-grid-col"));
var colSpecs = columns.map(col => {
var obj = {};
for (var i = col.attributes.length - 1; i >= 0; i--) {
var attr = col.attributes.item(i);
obj[attr.name] = attr.value;
}
parseCellTemplate(col, obj);
return obj;
});
var modelSpecs = {};
modelSpecs["fields"] = {};
columns.forEach(col => {
var colField = col.getAttribute("field");
if (colField != null) {
var model = col.querySelector("kendo-model");
if (model != null) {
var modelValidation = model.querySelector("kendo-model-validation");
var modelObj = {}
for (var i = model.attributes.length - 1; i >= 0; i--) {
var attr = model.attributes.item(i);
if (attr.name == "identifier") {
if (attr.value == "true")
modelSpecs["id"] = colField;
}
else {
modelObj[attr.name] = attr.value;
}
}
modelSpecs["fields"][colField] = modelObj;
if (modelValidation != null) {
var modelValidationObj = {};
for (var i = modelValidation.attributes.length - 1; i >= 0; i--) {
var attr = modelValidation.attributes.item(i);
modelValidationObj[attr.name] = attr.value;
}
modelSpecs["fields"][colField]["validation"] = modelValidationObj;
}
}
}
});
// Remove any inner HTML from the element - we don't want it in the DOM
element.innerHTML = "";
instruction.kendoGridColumns = colSpecs;
instruction.kendoDataSourceModel = modelSpecs;
}
function parseCellTemplate(element, spec) {
var template = element.querySelector("kendo-template");
if (template)
spec.template = template.innerHTML;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment