New Case Study:See how Anthropic automated 95% of dependency reviews with Socket.Learn More
Socket
Sign inDemoInstall
Socket

@vaadin/vaadin-grid

Package Overview
Dependencies
Maintainers
14
Versions
354
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

@vaadin/vaadin-grid - npm Package Compare versions

Comparing version 5.1.0 to 5.2.0-alpha1

test/renderers.html

60

demo/grid-basic-demos.js

@@ -12,4 +12,60 @@ import { html } from '@polymer/polymer/lib/utils/html-tag.js';

<h3>Content Renderer Function</h3>
<vaadin-demo-snippet id="grid-columns-demos-renderer-functions">
<template preserve-content="">
<iron-ajax auto="" url="https://demo.vaadin.com/demo-data/1.0/people?count=200"></iron-ajax>
<h3>Basic Binding</h3>
<vaadin-grid aria-label="Content Renderer Function">
<vaadin-grid-column width="60px" flex-grow="0"></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
<vaadin-grid-column width="8em"></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-columns-demos-renderer-functions', function(document) {
const ajax = document.querySelector('iron-ajax');
const grid = document.querySelector('vaadin-grid');
const columns = document.querySelectorAll('vaadin-grid-column');
ajax.addEventListener('last-response-changed', function(e) {
grid.items = e.target.lastResponse.result;
});
columns[0].renderer = function(root, column, model) {
root.innerHTML = model.index;
};
columns[0].headerRenderer = columns[0].footerRenderer = function(root, column) {
root.innerHTML = '#';
};
columns[1].renderer = function(root, column, model) {
root.innerHTML = model.item.firstName;
};
columns[1].headerRenderer = columns[1].footerRenderer = function(root, column) {
root.innerHTML = 'First Name';
};
columns[2].renderer = function(root, column, model) {
root.innerHTML = model.item.lastName;
};
columns[2].headerRenderer = columns[2].footerRenderer = function(root, column) {
root.innerHTML = 'Last Name';
};
columns[3].renderer = function(root, column, model) {
root.innerHTML =
'<div style="white-space: normal">' +
model.item.address.street + ', ' + model.item.address.city +
'</div>';
};
columns[3].headerRenderer = columns[3].footerRenderer = function(root, column) {
root.innerHTML = 'Address';
};
});
&lt;/script>
</template>
</vaadin-demo-snippet>
<h3>Defining Content with Polymer Templates</h3>
<p>

@@ -93,3 +149,2 @@ Cells contents can be defined using <code>&lt;template&gt;</code> elements.

<vaadin-grid aria-label="Two-way Binding Example" items="[[users.result]]">
<vaadin-grid-column>

@@ -113,3 +168,2 @@ <template class="header">First Name</template>

</vaadin-grid-column>
</vaadin-grid>

@@ -116,0 +170,0 @@ </template>

402

demo/grid-columns-demos.js

@@ -12,3 +12,2 @@ import { html } from '@polymer/polymer/lib/utils/html-tag.js';

<h3>Column Grouping</h3>

@@ -27,60 +26,71 @@ <p>

<template preserve-content="">
<dom-bind>
<template>
<x-data-provider></x-data-provider>
<x-data-provider data-provider="{{dataProvider}}"></x-data-provider>
<vaadin-grid aria-label="Column Grouping Example" size="200">
<vaadin-grid-column width="30px" flex-grow="0" name="index"></vaadin-grid-column>
<vaadin-grid-column width="60px" flex-grow="0" name="thumbnail"></vaadin-grid-column>
<vaadin-grid aria-label="Column Grouping Example" data-provider="[[dataProvider]]" size="200">
<vaadin-grid-column-group class="group">
<vaadin-grid-column width="calc(25% - 20px)" name="First"></vaadin-grid-column>
<vaadin-grid-column width="calc(25% - 20px)" name="Last"></vaadin-grid-column>
</vaadin-grid-column-group>
<vaadin-grid-column width="30px" flex-grow="0">
<template class="header">#</template>
<template>[[index]]</template>
</vaadin-grid-column>
<vaadin-grid-column-group class="group">
<vaadin-grid-column width="calc(25% - 20px)" name="City"></vaadin-grid-column>
<vaadin-grid-column width="calc(25% - 20px)" name="State"></vaadin-grid-column>
<vaadin-grid-column width="200px" name="Street"></vaadin-grid-column>
</vaadin-grid-column-group>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-columns-demos-column-grouping', function(document) {
const grid = document.querySelector('vaadin-grid');
<vaadin-grid-column width="60px" flex-grow="0">
<template class="header">
<div aria-label="Picture"></div>
</template>
<template>
<iron-image width="30" height="30" sizing="cover" alt="[[item.name.first]] [[item.name.last]]" src="[[item.picture.thumbnail]]"></iron-image>
</template>
</vaadin-grid-column>
const dataProvider = document.querySelector('x-data-provider');
grid.dataProvider = dataProvider.dataProvider;
<vaadin-grid-column-group>
<template class="header">Name</template>
const columns = grid.querySelectorAll('vaadin-grid-column');
<vaadin-grid-column width="calc(25% - 20px)">
<template class="header">First</template>
<template>[[item.name.first]]</template>
</vaadin-grid-column>
columns.forEach(function(column, index) {
column.headerRenderer = function(root, column, model) {
root.innerHTML = '';
<vaadin-grid-column width="calc(25% - 20px)">
<template class="header">Last</template>
<template>[[item.name.last]]</template>
</vaadin-grid-column>
</vaadin-grid-column-group>
if (index === 0) {
root.textContent = '#';
} else if (index === 1) {
root.innerHTML = '<div aria-label="Picture"></div>';
} else {
root.textContent = column.getAttribute('name');
}
};
column.renderer = function(root, column, model) {
root.innerHTML = '';
<vaadin-grid-column-group>
<template class="header">Location</template>
const propName = column.getAttribute('name').toLowerCase();
if (index === 0) {
root.textContent = model[propName];
} else if (index === 1) {
root.innerHTML =
'<iron-image width="30" height="30" sizing="cover" ' +
'alt="' + model.item.name.first + model.item.name.last + '"' +
'src="' + model.item.picture.thumbnail + '">' +
'</iron-image>';
} else if (index < 4) {
root.textContent = model.item.name[propName];
} else {
root.textContent = model.item.location[propName];
}
};
});
<vaadin-grid-column width="calc(25% - 20px)">
<template class="header">City</template>
<template>[[item.location.city]]</template>
</vaadin-grid-column>
const groups = document.querySelectorAll('.group');
groups[0].headerRenderer = function(root, column, model) {
root.textContent = 'Name';
};
groups[1].headerRenderer = function(root, column, model) {
root.textContent = 'Location';
};
<vaadin-grid-column width="calc(25% - 20px)">
<template class="header">State</template>
<template>[[item.location.state]]</template>
</vaadin-grid-column>
<vaadin-grid-column width="200px">
<template class="header">Street</template>
<template><p style="white-space: normal">[[item.location.street]]</p></template>
</vaadin-grid-column>
</vaadin-grid-column-group>
</vaadin-grid>
</template>
</dom-bind>
});
&lt;/script>
</template>

@@ -101,41 +111,68 @@ </vaadin-demo-snippet>

<template preserve-content="">
<dom-bind>
<template>
<x-data-provider data-provider="{{dataProvider}}"></x-data-provider>
<vaadin-checkbox checked="{{frozen}}">Freeze First Two Columns</vaadin-checkbox>
<x-data-provider></x-data-provider>
<vaadin-grid aria-label="Freezing Columns Example" data-provider="[[dataProvider]]" size="200">
<vaadin-checkbox>Freeze First Two Columns</vaadin-checkbox>
<vaadin-grid-column width="60px" flex-grow="0" frozen="[[frozen]]">
<template class="header">#</template>
<template>[[index]]</template>
</vaadin-grid-column>
<vaadin-grid aria-label="Freezing Columns Example" size="200">
<vaadin-grid-column width="60px" flex-grow="0"></vaadin-grid-column>
<vaadin-grid-column width="60px" flex-grow="0"></vaadin-grid-column>
<vaadin-grid-column width="33%"></vaadin-grid-column>
<vaadin-grid-column width="33%"></vaadin-grid-column>
<vaadin-grid-column width="33%"></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-columns-demos-freezing-columns', function(document) {
const grid = document.querySelector('vaadin-grid');
const checkBox = document.querySelector('vaadin-checkbox');
<vaadin-grid-column width="60px" flex-grow="0" frozen="[[frozen]]">
<template class="header">
<div aria-label="Picture"></div>
</template>
<template>
<iron-image width="30" height="30" sizing="cover" alt="[[item.name.first]] [[item.name.last]]" src="[[item.picture.thumbnail]]"></iron-image>
</template>
</vaadin-grid-column>
checkBox.addEventListener('checked-changed', function(event) {
columns[0].frozen = columns[1].frozen = event.detail.value;
});
<vaadin-grid-column width="33%">
<template class="header">First Name</template>
<template>[[item.name.first]]</template>
</vaadin-grid-column>
const columns = document.querySelectorAll('vaadin-grid-column');
<vaadin-grid-column width="33%">
<template class="header">Last Name</template>
<template>[[item.name.last]]</template>
</vaadin-grid-column>
columns[1].headerRenderer = function(root, column, model) {
root.innerHTML = '<div aria-label="Picture"></div>';
};
<vaadin-grid-column width="33%">
<template class="header">Email</template>
<template>[[item.email]]</template>
</vaadin-grid-column>
columns[2].headerRenderer = function(root, column, model) {
root.textContent = 'First Name';
};
</vaadin-grid>
</template>
</dom-bind>
columns[3].headerRenderer = function(root, column, model) {
root.textContent = 'Last Name';
};
columns[4].headerRenderer = function(root, column, model) {
root.textContent = 'Email';
};
columns[0].renderer = function(root, column, model) {
root.textContent = model.index;
};
columns[1].renderer = function(root, column, model) {
root.innerHTML =
'<iron-image width="30" height="30" sizing="cover" ' +
'alt="' + model.item.name.first + model.item.name.last + '"' +
'src="' + model.item.picture.thumbnail + '">' +
'</iron-image>';
};
columns[2].renderer = function(root, column, model) {
root.textContent = model.item.name.first;
};
columns[3].renderer = function(root, column, model) {
root.textContent = model.item.name.last;
};
columns[4].renderer = function(root, column, model) {
root.textContent = model.item.email;
};
const dataProvider = document.querySelector('x-data-provider');
grid.dataProvider = dataProvider.dataProvider;
});
&lt;/script>
</template>

@@ -149,48 +186,74 @@ </vaadin-demo-snippet>

</p>
<p>
<b>Hint:</b> Using <code>hidden</code> together with <code>&lt;iron-media-query&gt;</code>
is an easy way to create a responsive grid.
</p>
<vaadin-demo-snippet id="grid-columns-demos-hiding-columns">
<template preserve-content="">
<dom-bind>
<template>
<x-data-provider data-provider="{{dataProvider}}"></x-data-provider>
<vaadin-checkbox checked="{{hidden}}">Hide First Two Columns</vaadin-checkbox>
<iron-media-query query-matches="{{hidden}}" query="(max-width: 700px)"></iron-media-query>
<x-data-provider></x-data-provider>
<vaadin-grid aria-label="Hiding Columns Example" data-provider="[[dataProvider]]" size="200">
<vaadin-checkbox>Hide First Two Columns</vaadin-checkbox>
<vaadin-grid-column width="60px" flex-grow="0" hidden="[[hidden]]">
<template class="header">#</template>
<template>[[index]]</template>
</vaadin-grid-column>
<vaadin-grid aria-label="Hiding Columns Example" size="200">
<vaadin-grid-column width="60px" flex-grow="0"></vaadin-grid-column>
<vaadin-grid-column width="60px" flex-grow="0"></vaadin-grid-column>
<vaadin-grid-column width="33%"></vaadin-grid-column>
<vaadin-grid-column width="33%"></vaadin-grid-column>
<vaadin-grid-column width="33%"></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-columns-demos-hiding-columns', function(document) {
const grid = document.querySelector('vaadin-grid');
const checkBox = document.querySelector('vaadin-checkbox');
<vaadin-grid-column width="60px" flex-grow="0" hidden="[[hidden]]">
<template class="header">
<div aria-label="Picture"></div>
</template>
<template>
<iron-image width="30" height="30" sizing="cover" alt="[[item.name.first]] [[item.name.last]]" src="[[item.picture.thumbnail]]"></iron-image>
</template>
</vaadin-grid-column>
checkBox.addEventListener('checked-changed', function(event) {
columns[0].hidden = columns[1].hidden = event.detail.value;
});
<vaadin-grid-column width="33%">
<template class="header">First Name</template>
<template>[[item.name.first]]</template>
</vaadin-grid-column>
const columns = document.querySelectorAll('vaadin-grid-column');
<vaadin-grid-column width="33%">
<template class="header">Last Name</template>
<template>[[item.name.last]]</template>
</vaadin-grid-column>
columns[0].headerRenderer = function(root, column, model) {
root.textContent = '#';
};
<vaadin-grid-column width="33%">
<template class="header">Email</template>
<template>[[item.email]]</template>
</vaadin-grid-column>
columns[1].headerRenderer = function(root, column, model) {
root.innerHTML = '<div aria-label="Picture"></div>';
};
</vaadin-grid>
</template>
</dom-bind>
columns[2].headerRenderer = function(root, column, model) {
root.textContent = 'First Name';
};
columns[3].headerRenderer = function(root, column, model) {
root.textContent = 'Last Name';
};
columns[4].headerRenderer = function(root, column, model) {
root.textContent = 'Email';
};
columns[0].renderer = function(root, column, model) {
root.textContent = model.index;
};
columns[1].renderer = function(root, column, model) {
root.innerHTML =
'<iron-image width="30" height="30" sizing="cover" ' +
'alt="' + model.item.name.first + model.item.name.last + '"' +
'src="' + model.item.picture.thumbnail + '">' +
'</iron-image>';
};
columns[2].renderer = function(root, column, model) {
root.textContent = model.item.name.first;
};
columns[3].renderer = function(root, column, model) {
root.textContent = model.item.name.last;
};
columns[4].renderer = function(root, column, model) {
root.textContent = model.item.email;
};
const dataProvider = document.querySelector('x-data-provider');
grid.dataProvider = dataProvider.dataProvider;
});
&lt;/script>
</template>

@@ -214,58 +277,71 @@ </vaadin-demo-snippet>

<template preserve-content="">
<dom-bind>
<template>
<x-data-provider data-provider="{{dataProvider}}"></x-data-provider>
<x-data-provider></x-data-provider>
<vaadin-grid aria-label="Reordering and Resizing Columns Example" data-provider="[[dataProvider]]" size="200" column-reordering-allowed="">
<vaadin-grid aria-label="Reordering and Resizing Columns Example" size="200" column-reordering-allowed="">
<vaadin-grid-column width="30px" flex-grow="0" name="index" resizable=""></vaadin-grid-column>
<vaadin-grid-column width="60px" flex-grow="0" name="thumbnail" resizable=""></vaadin-grid-column>
<vaadin-grid-column width="30px" flex-grow="0" resizable="">
<template class="header">#</template>
<template>[[index]]</template>
</vaadin-grid-column>
<vaadin-grid-column-group id="group1" resizable="">
<vaadin-grid-column width="calc(25% - 20px)" name="First"></vaadin-grid-column>
<vaadin-grid-column width="calc(25% - 20px)" name="Last"></vaadin-grid-column>
</vaadin-grid-column-group>
<vaadin-grid-column width="60px" flex-grow="0" resizable="">
<template class="header">
<div aria-label="Picture"></div>
</template>
<template>
<iron-image width="30" height="30" sizing="cover" alt="[[item.name.first]] [[item.name.last]]" src="[[item.picture.thumbnail]]"></iron-image>
</template>
</vaadin-grid-column>
<vaadin-grid-column-group id="group2" resizable="">
<vaadin-grid-column width="calc(25% - 20px)" name="City"></vaadin-grid-column>
<vaadin-grid-column width="calc(25% - 20px)" name="State"></vaadin-grid-column>
<vaadin-grid-column width="200px" name="Street"></vaadin-grid-column>
</vaadin-grid-column-group>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-columns-demos-reordering-and-resizing-columns', function(document) {
const grid = document.querySelector('vaadin-grid');
<vaadin-grid-column-group resizable="">
<template class="header">Name</template>
const dataProvider = document.querySelector('x-data-provider');
grid.dataProvider = dataProvider.dataProvider;
<vaadin-grid-column width="calc(25% - 20px)">
<template class="header">First</template>
<template>[[item.name.first]]</template>
</vaadin-grid-column>
const columns = grid.querySelectorAll('vaadin-grid-column');
<vaadin-grid-column width="calc(25% - 20px)">
<template class="header">Last</template>
<template>[[item.name.last]]</template>
</vaadin-grid-column>
</vaadin-grid-column-group>
columns.forEach(function(column, index) {
column.headerRenderer = function(root, column, model) {
root.innerHTML = '';
<vaadin-grid-column-group resizable="">
<template class="header">Location</template>
if (index === 0) {
root.textContent = '#';
} else if (index === 1) {
root.innerHTML = '<div aria-label="Picture"></div>';
} else {
root.textContent = column.getAttribute('name');
}
};
<vaadin-grid-column width="calc(25% - 20px)">
<template class="header">City</template>
<template>[[item.location.city]]</template>
</vaadin-grid-column>
column.renderer = function(root, column, model) {
root.innerHTML = '';
<vaadin-grid-column width="calc(25% - 20px)">
<template class="header">State</template>
<template>[[item.location.state]]</template>
</vaadin-grid-column>
const propName = column.getAttribute('name').toLowerCase();
if (index === 0) {
root.textContent = model[propName];
} else if (index === 1) {
root.innerHTML =
'<iron-image width="30" height="30" sizing="cover" ' +
'alt="' + model.item.name.first + model.item.name.last + '"' +
'src="' + model.item.picture.thumbnail + '">' +
'</iron-image>';
} else if (index < 4) {
root.textContent = model.item.name[propName];
} else {
root.textContent = model.item.location[propName];
}
};
});
<vaadin-grid-column width="200px" resizable="">
<template class="header">Street</template>
<template>[[item.location.street]]</template>
</vaadin-grid-column>
</vaadin-grid-column-group>
</vaadin-grid>
</template>
</dom-bind>
const group1 = document.querySelector('#group1');
const group2 = document.querySelector('#group2');
group1.headerRenderer = function(root, column, model) {
root.textContent = 'Name';
};
group2.headerRenderer = function(root, column, model) {
root.textContent = 'Location';
};
});
&lt;/script>
</template>

@@ -272,0 +348,0 @@ </vaadin-demo-snippet>

@@ -21,3 +21,3 @@ import { html } from '@polymer/polymer/lib/utils/html-tag.js';

<p>
Column <code>&lt;template&gt;</code> elements and data binding can be used to implement inline editing.
Grid renderers and JavaScript functions can be used to implement inline editing.
</p>

@@ -29,118 +29,132 @@ <p>

<template preserve-content="">
<x-crud></x-crud>
<dom-module id="x-crud">
<template preserve-content="">
<style>
vaadin-grid vaadin-text-field {
width: 100%;
}
</style>
<x-array-data-provider items="{{items}}" size="200"></x-array-data-provider>
<style>
vaadin-grid vaadin-text-field {
width: 100%;
}
<div style="margin-bottom: 20px">
<vaadin-text-field id="firstname" label="First Name"></vaadin-text-field>
<vaadin-text-field id="lastname" label="Last Name"></vaadin-text-field>
<vaadin-button on-click="_add">Add</vaadin-button>
</div>
vaadin-grid vaadin-button {
margin-left: 5px;
}
</style>
<x-array-data-provider></x-array-data-provider>
<vaadin-grid theme="compact" id="grid" items="[[items]]">
<div style="margin-bottom: 20px">
<vaadin-text-field id="firstname" label="First Name"></vaadin-text-field>
<vaadin-text-field id="lastname" label="Last Name"></vaadin-text-field>
<vaadin-button id="add-btn">Add</vaadin-button>
</div>
<vaadin-grid-column resizable="">
<template class="header">First Name</template>
<template>
<vaadin-text-field id="first-[[index]]" value="[[item.name.first]]" on-input="_storeFirst" readonly\$="[[!_isEditing(editing, item)]]"></vaadin-text-field>
</template>
</vaadin-grid-column>
<vaadin-grid theme="compact">
<vaadin-grid-column name="First Name" resizable=""></vaadin-grid-column>
<vaadin-grid-column name="Last Name" resizable=""></vaadin-grid-column>
<vaadin-grid-column name="E-Mail" width="12em" resizable=""></vaadin-grid-column>
<vaadin-grid-column width="14em"></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-crud-demos-crud', function(document) {
const grid = document.querySelector('vaadin-grid');
const firstname = document.querySelector('#firstname');
const lastname = document.querySelector('#lastname');
<vaadin-grid-column resizable="">
<template class="header">Last Name</template>
<template>
<vaadin-text-field id="last-[[index]]" value="[[item.name.last]]" readonly\$="[[!_isEditing(editing, item)]]"></vaadin-text-field>
</template>
</vaadin-grid-column>
const addBtn = document.querySelector('#add-btn');
<vaadin-grid-column width="12em" resizable="">
<template class="header">Email</template>
<template>
<div>[[item.name.first]].[[item.name.last]]@example.com</div>
</template>
</vaadin-grid-column>
addBtn.addEventListener('click', function() {
if (firstname.value && lastname.value) {
grid.items.unshift({name: {first: firstname.value, last: lastname.value}});
grid.clearCache();
firstname.value = lastname.value = '';
} else {
alert('First Name and Last Name required');
}
});
<vaadin-grid-column width="14em">
<template>
<div style="text-align: right;">
<vaadin-button id="edit-button" hidden="[[editing]]" on-click="_edit" focus-target\$="[[!editing]]" theme="icon" aria-label="Edit"><iron-icon icon="lumo:edit"></iron-icon></vaadin-button>
<vaadin-button hidden="[[editing]]" on-click="_remove" theme="icon error" aria-label="Delete"><iron-icon icon="lumo:cross"></iron-icon></vaadin-button>
<vaadin-button hidden="[[!_isEditing(editing, item)]]" on-click="_save" focus-target\$="[[editing]]" theme="primary">Save</vaadin-button>
<vaadin-button hidden="[[!_isEditing(editing, item)]]" on-click="_cancel">Cancel</vaadin-button>
</div>
</template>
</vaadin-grid-column>
const columns = document.querySelectorAll('vaadin-grid-column');
</vaadin-grid>
</template>
<script>
window.addDemoReadyListener('#grid-crud-demos-crud', function(document) {
Polymer({
is: 'x-crud',
columns[0].headerRenderer =
columns[1].headerRenderer =
columns[2].headerRenderer = function(root, column) {
root.textContent = column.getAttribute('name');
};
properties: {
editing: Object
},
columns[0].renderer =
columns[1].renderer = function(root, column, model) {
let textField = root.firstElementChild;
if (!textField) {
textField = window.document.createElement('vaadin-text-field');
root.appendChild(textField);
}
const property = column == columns[0] ? 'first' : 'last';
// set an id so as we can find it in the dom when clicking on action buttons.
textField.id = property + model.index;
textField.value = model.item.name[property];
textField.readonly = true;
textField.setAttribute('focus-target', true);
};
ready: function() {
this.editing = null;
},
columns[2].renderer = function(root, column, model) {
root.textContent = model.item.name.first + '.' + model.item.name.last + '@example.com';
};
_isEditing: function(editing, item) {
return item === editing;
},
columns[3].renderer = function(root, column, model) {
let wrapper = root.firstElementChild;
if (!wrapper) {
root.innerHTML =
'<div style="text-align: right">' +
'<vaadin-button aria-label="Edit" theme="icon" focus-target>' +
'<iron-icon icon="lumo:edit"></iron-icon>' +
'</vaadin-button>' +
'<vaadin-button aria-label="Delete" theme="icon error">' +
'<iron-icon icon="lumo:cross"></iron-icon>' +
'</vaadin-button>' +
'<vaadin-button aria-label="Save" theme="primary" focus-target hidden>Save</vaadin-button>' +
'<vaadin-button aria-label="Cancel" hidden>Cancel</vaadin-button>' +
'</div>';
wrapper = root.firstElementChild;
_edit: function(e) {
var item = e.model.item;
this.editing = item;
const buttons = wrapper.querySelectorAll('vaadin-button');
// EDIT
buttons[0].addEventListener('click', function() {
updateTextFieldsVisibility(wrapper.idx, true);
updateButtonsVisibility(buttons, wrapper.idx, true);
grid.querySelector('#first' + wrapper.idx).focus();
});
// DELETE
buttons[1].addEventListener('click', function(event) {
grid.items.splice(wrapper.idx, 1);
grid.clearCache();
});
// SAVE
buttons[2].addEventListener('click', function() {
grid.items[wrapper.idx].name.first = grid.querySelector('#first' + wrapper.idx).value;
grid.items[wrapper.idx].name.last = grid.querySelector('#last' + wrapper.idx).value;
buttons[3].click();
});
// CANCEL
buttons[3].addEventListener('click', function(event) {
updateTextFieldsVisibility(wrapper.idx, false);
updateButtonsVisibility(buttons, wrapper.idx, false);
grid.clearCache();
buttons[0].focus();
});
}
this.\$.grid.querySelector('#first-' + e.model.index).focus();
},
// We reuse rendered content, but maintain a property with the index for actions
wrapper.idx = model.index;
};
_save: function(e) {
var item = e.model.item;
item.name.first = this.\$.grid.querySelector('#first-' + e.model.index).value;
item.name.last = this.\$.grid.querySelector('#last-' + e.model.index).value;
function updateTextFieldsVisibility(index, editing) {
grid.querySelector('#first' + index).readonly = !editing;
grid.querySelector('#last' + index).readonly = !editing;
}
this.editing = null;
function updateButtonsVisibility(buttons, index, editing) {
buttons[0].hidden = buttons[1].hidden = editing;
buttons[2].hidden = buttons[3].hidden = !editing;
}
this.\$.grid.clearCache();
this.\$.grid.querySelector('#edit-button').focus();
},
_cancel: function() {
this.editing = null;
this.\$.grid.clearCache();
this.\$.grid.querySelector('#edit-button').focus();
},
_add: function(e) {
if (this.\$.firstname.value !== '' && this.\$.lastname.value !== '') {
this.items.unshift({name: {first: this.\$.firstname.value, last: this.\$.lastname.value}});
this.\$.grid.clearCache();
this.\$.firstname.value = '';
this.\$.lastname.value = '';
} else {
alert('First Name and Last Name required');
}
},
_remove: function(e) {
var index = this.items.indexOf(e.model.item);
this.items.splice(index, 1);
this.\$.grid.clearCache();
}
});
});
&lt;/script>
</dom-module>
const dataProvider = document.querySelector('x-array-data-provider');
dataProvider.size = 200;
grid.items = dataProvider.items;
});
&lt;/script>
</template>

@@ -147,0 +161,0 @@ </vaadin-demo-snippet>

@@ -12,3 +12,2 @@ import { html } from '@polymer/polymer/lib/utils/html-tag.js';

<h3>Assigning Array Data</h3>

@@ -18,42 +17,44 @@ <p>An array of objects can be assigned to the <code>items</code> property.</p>

<template preserve-content="">
<x-array-data-example></x-array-data-example>
<dom-module id="x-array-data-example">
<template preserve-content="">
<vaadin-grid aria-label="Array Data Example" items="[[items]]">
<vaadin-grid aria-label="Array Data Example">
<vaadin-grid-column width="60px" flex-grow="0"></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-data-demos-assigning-array-data', function(document) {
const grid = document.querySelector('vaadin-grid');
const columns = document.querySelectorAll('vaadin-grid-column');
<vaadin-grid-column width="60px" flex-grow="0">
<template class="header">#</template>
<template>[[index]]</template>
</vaadin-grid-column>
columns[0].renderer = function(root, column, model) {
root.textContent = model.index;
};
<vaadin-grid-column>
<template class="header">First Name</template>
<template>[[item.firstName]]</template>
</vaadin-grid-column>
columns[1].renderer = function(root, column, model) {
root.textContent = model.item.firstName;
};
<vaadin-grid-column>
<template class="header">Last Name</template>
<template>[[item.lastName]]</template>
</vaadin-grid-column>
columns[2].renderer = function(root, column, model) {
root.textContent = model.item.lastName;
};
</vaadin-grid>
</template>
<script>
window.addDemoReadyListener('#grid-data-demos-assigning-array-data', function(document) {
Polymer({
is: 'x-array-data-example',
columns[0].headerRenderer = function(root) {
root.textContent = '#';
};
ready: function() {
var items = [];
columns[1].headerRenderer = function(root) {
root.textContent = 'First Name';
};
for (var i = 0; i < 100; i++) {
items.push({firstName: 'First Name ' + i, lastName: 'Last Name ' + i});
}
columns[2].headerRenderer = function(root) {
root.textContent = 'Last Name';
};
this.items = items;
}
});
});
&lt;/script>
</dom-module>
const items = [];
for (var i = 0; i < 100; i++) {
items.push({firstName: 'First Name ' + i, lastName: 'Last Name ' + i});
}
grid.items = items;
});
&lt;/script>
</template>

@@ -65,62 +66,71 @@ </vaadin-demo-snippet>

<p>
The <code>items</code> property can be modified using Polymer's array mutation methods.
The <code>items</code> property can be modified using array manipulations.
</p>
<vaadin-demo-snippet id="grid-data-demos-dynamic-array-data">
<template preserve-content="">
<x-dynamic-data-example></x-dynamic-data-example>
<dom-module id="x-dynamic-data-example">
<template preserve-content="">
<style>
vaadin-button {
margin-bottom: 20px;
}
</style>
<vaadin-button raised="" on-click="_add">Add Item</vaadin-button>
<vaadin-button raised="" on-click="_remove">Remove Item</vaadin-button>
<style>
vaadin-button {
margin-bottom: 20px;
}
</style>
<vaadin-button raised="" id="add-btn">Add Item</vaadin-button>
<vaadin-button raised="" id="remove-btn">Remove Item</vaadin-button>
<vaadin-grid aria-label="Dynamic Data Example" items="[[items]]">
<vaadin-grid aria-label="Dynamic Data Example">
<vaadin-grid-column width="60px" flex-grow="0"></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-data-demos-dynamic-array-data', function(document) {
const grid = document.querySelector('vaadin-grid');
const addBtn = document.querySelector('#add-btn');
const removeBtn = document.querySelector('#remove-btn');
<vaadin-grid-column width="60px" flex-grow="0">
<template class="header">#</template>
<template>[[index]]</template>
</vaadin-grid-column>
addBtn.addEventListener('click', function() {
const newItemsArray = grid.items.slice(0);
newItemsArray.push({firstName: 'First Name ' + newItemsArray.length, lastName: 'Last Name ' + newItemsArray.length});
grid.items = newItemsArray;
});
<vaadin-grid-column>
<template class="header">First Name</template>
<template>[[item.firstName]]</template>
</vaadin-grid-column>
removeBtn.addEventListener('click', function() {
const newItemsArray = grid.items.slice(0);
newItemsArray.pop();
grid.items = newItemsArray;
});
<vaadin-grid-column>
<template class="header">Last Name</template>
<template>[[item.lastName]]</template>
</vaadin-grid-column>
const columns = document.querySelectorAll('vaadin-grid-column');
</vaadin-grid>
</template>
<script>
window.addDemoReadyListener('#grid-data-demos-dynamic-array-data', function(document) {
Polymer({
is: 'x-dynamic-data-example',
columns[0].renderer = function(root, column, model) {
root.textContent = model.index;
};
ready: function() {
var items = [];
columns[1].renderer = function(root, column, model) {
root.textContent = model.item.firstName;
};
for (var i = 0; i < 10; i++) {
items.push({firstName: 'First Name ' + i, lastName: 'Last Name ' + i});
}
columns[2].renderer = function(root, column, model) {
root.textContent = model.item.lastName;
};
this.items = items;
},
columns[0].headerRenderer = function(root) {
root.textContent = '#';
};
_add: function() {
this.push('items', {firstName: 'First Name ' + this.items.length, lastName: 'Last Name ' + this.items.length});
},
columns[1].headerRenderer = function(root) {
root.textContent = 'First Name';
};
_remove: function() {
this.pop('items');
}
});
});
&lt;/script>
</dom-module>
columns[2].headerRenderer = function(root) {
root.textContent = 'Last Name';
};
const items = [];
for (var i = 0; i < 100; i++) {
items.push({firstName: 'First Name ' + i, lastName: 'Last Name ' + i});
}
grid.items = items;
});
&lt;/script>
</template>

@@ -137,58 +147,67 @@ </vaadin-demo-snippet>

<template preserve-content="">
<x-dynamic-height-example></x-dynamic-height-example>
<dom-module id="x-dynamic-height-example">
<template preserve-content="">
<style>
vaadin-button {
margin-bottom: 20px;
}
</style>
<vaadin-button raised="" on-click="_add">Add Item</vaadin-button>
<vaadin-button raised="" on-click="_remove">Remove Item</vaadin-button>
<style>
vaadin-button {
margin-bottom: 20px;
}
</style>
<vaadin-button raised="" id="add-btn">Add Item</vaadin-button>
<vaadin-button raised="" id="remove-btn">Remove Item</vaadin-button>
<vaadin-grid aria-label="Dynamic Data Example" items="[[items]]" height-by-rows="">
<vaadin-grid aria-label="Dynamic Data Example" height-by-rows="">
<vaadin-grid-column width="60px" flex-grow="0"></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-data-demos-dynamic-height', function(document) {
const grid = document.querySelector('vaadin-grid');
const addBtn = document.querySelector('#add-btn');
const removeBtn = document.querySelector('#remove-btn');
<vaadin-grid-column width="60px" flex-grow="0">
<template class="header">#</template>
<template>[[index]]</template>
</vaadin-grid-column>
addBtn.addEventListener('click', function() {
const newItemsArray = grid.items.slice(0);
newItemsArray.push({firstName: 'First Name ' + newItemsArray.length, lastName: 'Last Name ' + newItemsArray.length});
grid.items = newItemsArray;
});
<vaadin-grid-column>
<template class="header">First Name</template>
<template>[[item.firstName]]</template>
</vaadin-grid-column>
removeBtn.addEventListener('click', function() {
const newItemsArray = grid.items.slice(0);
newItemsArray.pop();
grid.items = newItemsArray;
});
<vaadin-grid-column>
<template class="header">Last Name</template>
<template>[[item.lastName]]</template>
</vaadin-grid-column>
const columns = document.querySelectorAll('vaadin-grid-column');
</vaadin-grid>
</template>
<script>
window.addDemoReadyListener('#grid-data-demos-dynamic-height', function(document) {
Polymer({
is: 'x-dynamic-height-example',
columns[0].renderer = function(root, column, model) {
root.textContent = model.index;
};
ready: function() {
var items = [];
columns[1].renderer = function(root, column, model) {
root.textContent = model.item.firstName;
};
for (var i = 0; i < 5; i++) {
items.push({firstName: 'First Name ' + i, lastName: 'Last Name ' + i});
}
columns[2].renderer = function(root, column, model) {
root.textContent = model.item.lastName;
};
this.items = items;
},
columns[0].headerRenderer = function(root) {
root.textContent = '#';
};
_add: function() {
this.push('items', {firstName: 'First Name ' + this.items.length, lastName: 'Last Name ' + this.items.length});
},
columns[1].headerRenderer = function(root) {
root.textContent = 'First Name';
};
_remove: function() {
this.pop('items');
}
});
});
&lt;/script>
</dom-module>
columns[2].headerRenderer = function(root) {
root.textContent = 'Last Name';
};
const items = [];
for (var i = 0; i < 5; i++) {
items.push({firstName: 'First Name ' + i, lastName: 'Last Name ' + i});
}
grid.items = items;
});
&lt;/script>
</template>

@@ -213,46 +232,49 @@ </vaadin-demo-snippet>

<template preserve-content="">
<x-remote-data-example></x-remote-data-example>
<dom-module id="x-remote-data-example">
<template preserve-content="">
<vaadin-grid aria-label="Remote Data Example" data-provider="[[dataProvider]]" size="[[size]]">
<vaadin-grid aria-label="Remote Data Example">
<vaadin-grid-column width="60px" flex-grow="0"></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-data-demos-assigning-remotefunction-data', function(document) {
const grid = document.querySelector('vaadin-grid');
<vaadin-grid-column width="60px" flex-grow="0">
<template class="header">#</template>
<template>[[index]]</template>
</vaadin-grid-column>
grid.size = 200;
grid.dataProvider = function(params, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
callback(JSON.parse(xhr.responseText).result);
};
var index = params.page * params.pageSize;
xhr.open('GET', 'https://demo.vaadin.com/demo-data/1.0/people?index=' + index + '&count=' + params.pageSize, true);
xhr.send();
};
<vaadin-grid-column>
<template class="header">First Name</template>
<template>[[item.firstName]]</template>
</vaadin-grid-column>
const columns = document.querySelectorAll('vaadin-grid-column');
<vaadin-grid-column>
<template class="header">Last Name</template>
<template>[[item.lastName]]</template>
</vaadin-grid-column>
columns[0].renderer = function(root, column, model) {
root.textContent = model.index;
};
</vaadin-grid>
</template>
<script>
window.addDemoReadyListener('#grid-data-demos-assigning-remotefunction-data', function(document) {
Polymer({
is: 'x-remote-data-example',
columns[1].renderer = function(root, column, model) {
root.textContent = model.item.firstName;
};
ready: function() {
this.size = 200;
this.dataProvider = function(params, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
callback(JSON.parse(xhr.responseText).result);
};
var index = params.page * params.pageSize;
xhr.open('GET', 'https://demo.vaadin.com/demo-data/1.0/people?index=' + index + '&count=' + params.pageSize, true);
xhr.send();
};
}
columns[2].renderer = function(root, column, model) {
root.textContent = model.item.lastName;
};
});
});
&lt;/script>
</dom-module>
columns[0].headerRenderer = function(root) {
root.textContent = '#';
};
columns[1].headerRenderer = function(root) {
root.textContent = 'First Name';
};
columns[2].headerRenderer = function(root) {
root.textContent = 'Last Name';
};
});
&lt;/script>
</template>

@@ -259,0 +281,0 @@ </vaadin-demo-snippet>

@@ -19,2 +19,162 @@ import { html } from '@polymer/polymer/lib/utils/html-tag.js';

&lt;&lt;&lt;&lt;&lt;&lt;&lt; HEAD:demo/grid-filtering-demos.html
=======
<h3>Sorting</h3>
<p>
<code>&lt;vaadin-grid-sorter&gt;</code> can be used to define sorting for a column.
The users in the example are sorted by last name initially.
</p>
<p>
<b>NOTE: You must explicitly import the <code>vaadin-grid-sorter.html</code> in order to use <code>&lt;vaadin-grid-sorter&gt;</code>.</b>
</p>
<vaadin-demo-snippet id="grid-sorting-filtering-demos-sorting">
<template preserve-content="">
<x-array-data-provider></x-array-data-provider>
<vaadin-checkbox>Enable Multi-Sorting</vaadin-checkbox>
<vaadin-grid aria-label="Sorting Example">
<vaadin-grid-column width="60px" flex-grow="0"></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-sorting-filtering-demos-sorting', function(document) {
const grid = document.querySelector('vaadin-grid');
const checkBox = document.querySelector('vaadin-checkbox');
checkBox.addEventListener('checked-changed', function(event) {
grid.multiSort = event.detail.value;
});
const dataProvider = document.querySelector('x-array-data-provider');
grid.items = dataProvider.items;
const columns = document.querySelectorAll('vaadin-grid-column');
columns[0].renderer = function(root, column, model) {
root.textContent = model.index;
};
columns[1].renderer = function(root, column, model) {
root.textContent = model.item.name.first;
};
columns[2].renderer = function(root, column, model) {
root.textContent = model.item.name.last;
};
columns[0].headerRenderer = function(root) {
root.textContent = '#';
};
columns[1].headerRenderer = function(root) {
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'name.first');
sorter.textContent = 'First Name';
root.appendChild(sorter);
};
columns[2].headerRenderer = function(root) {
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'name.last');
sorter.setAttribute('direction', 'asc');
sorter.textContent = 'Last Name';
root.appendChild(sorter);
};
});
&lt;/script>
</template>
</vaadin-demo-snippet>
<h3>Sorting with Data Provider</h3>
<p>
When the data is fetched from a data provider, the responsibility
of providing the correctly ordered data is on the data provider itself.
The data provider is asked for fresh sorted data whenever the sorting
order is changed on any <code>&lt;vaadin-grid-sorter&gt;</code>.
</p>
<p>
The effective <code>sortOrders</code> array will be included as one of
the data provider call options.
</p>
<p>
<b>Hint: </b>When using a data provider, <code>path</code> on the
<code>&lt;vaadin-grid-sorter&gt;</code> element can be set to any string,
instead of a property on the item object.
</p>
<vaadin-demo-snippet id="grid-sorting-filtering-demos-sorting-with-data-provider">
<template preserve-content="">
<vaadin-checkbox>Enable Multi-Sorting</vaadin-checkbox>
<vaadin-grid aria-label="Sorting Example">
<vaadin-grid-column width="60px" flex-grow="0"></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-sorting-filtering-demos-sorting-with-data-provider', function(document) {
const grid = document.querySelector('vaadin-grid');
const checkBox = document.querySelector('vaadin-checkbox');
checkBox.addEventListener('checked-changed', function(event) {
grid.multiSort = event.detail.value;
});
grid.size = 200;
grid.dataProvider = function(params, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
callback(JSON.parse(xhr.responseText).result);
};
var index = params.page * params.pageSize;
var url = 'https://demo.vaadin.com/demo-data/1.0/people?index=' + index + '&count=' + params.pageSize;
// \`params.sortOrders\` format: [{path: 'lastName', direction: 'asc'}, ...];
params.sortOrders.forEach(function(sort) {
url += '&orders[]=' + sort.path + ' ' + sort.direction;
});
xhr.open('GET', url, true);
xhr.send();
};
const columns = document.querySelectorAll('vaadin-grid-column');
columns[0].renderer = function(root, column, model) {
root.textContent = model.index;
};
columns[1].renderer = function(root, column, model) {
root.textContent = model.item.firstName;
};
columns[2].renderer = function(root, column, model) {
root.textContent = model.item.lastName;
};
columns[0].headerRenderer = function(root) {
root.textContent = '#';
};
columns[1].headerRenderer = function(root) {
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'firstName');
sorter.textContent = 'First Name';
root.appendChild(sorter);
};
columns[2].headerRenderer = function(root) {
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'lastName');
sorter.textContent = 'Last Name';
root.appendChild(sorter);
};
});
&lt;/script>
</template>
</vaadin-demo-snippet>
&gt;&gt;&gt;&gt;&gt;&gt;&gt; First iteration of demo conversion to prefer renderers:demo/grid-sorting-filtering-demos.html
<h3>Filtering</h3>

@@ -30,35 +190,55 @@ <p>

<template preserve-content="">
<dom-bind>
<template>
<x-array-data-provider></x-array-data-provider>
<vaadin-grid aria-label="Filtering Example">
<vaadin-grid-column width="60px" flex-grow="0"></vaadin-grid-column>
<vaadin-grid-column name="First"></vaadin-grid-column>
<vaadin-grid-column name="Last"></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-sorting-filtering-demos-filtering', function(document) {
const grid = document.querySelector('vaadin-grid');
const columns = grid.querySelectorAll('vaadin-grid-column');
<x-array-data-provider items="{{items}}"></x-array-data-provider>
columns[0].renderer = function(root, column, model) {
root.textContent = model.index;
};
<vaadin-grid aria-label="Filtering Example" items="[[items]]">
columns[0].headerRenderer = function(root) {
root.textContent = '#';
};
<vaadin-grid-column width="60px" flex-grow="0">
<template class="header">#</template>
<template>[[index]]</template>
</vaadin-grid-column>
columns.forEach(function(column, index) {
// Start from second column
if (index === 0) {
return;
}
<vaadin-grid-column>
<template class="header">
<vaadin-grid-filter aria-label="First Name" path="name.first" value="[[_filterFirstName]]">
<vaadin-text-field slot="filter" placeholder="First Name" value="{{_filterFirstName}}" focus-target=""></vaadin-text-field>
</vaadin-grid-filter>
</template>
<template>[[item.name.first]]</template>
</vaadin-grid-column>
const propName = column.getAttribute('name');
<vaadin-grid-column>
<template class="header">
<vaadin-grid-filter aria-label="Last Name" path="name.last" value="[[_filterLastName]]">
<vaadin-text-field slot="filter" placeholder="Last Name" value="{{_filterLastName}}" focus-target=""></vaadin-text-field>
</vaadin-grid-filter>
</template>
<template>[[item.name.last]]</template>
</vaadin-grid-column>
column.renderer = function(root, column, model) {
root.textContent = model.item.name[propName.toLowerCase()];
};
</vaadin-grid>
</template>
</dom-bind>
column.headerRenderer = function(root) {
const filter = window.document.createElement('vaadin-grid-filter');
filter.setAttribute('path', 'name.' + propName.toLowerCase());
const textField = window.document.createElement('vaadin-text-field');
textField.setAttribute('slot', 'filter');
textField.setAttribute('focus-target', true);
textField.setAttribute('placeholder', propName + ' Name');
textField.addEventListener('value-changed', function(event) {
filter.value = event.detail.value;
});
filter.appendChild(textField);
root.appendChild(filter);
};
});
const dataProvider = document.querySelector('x-array-data-provider');
grid.items = dataProvider.items;
});
&lt;/script>
</template>

@@ -85,70 +265,77 @@ </vaadin-demo-snippet>

<template preserve-content="">
<x-remote-filtering-example></x-remote-filtering-example>
<dom-module id="x-remote-filtering-example">
<template preserve-content="">
<vaadin-grid aria-label="Filtering with Data Provider Example" id="grid">
<vaadin-grid aria-label="Filtering with Data Provider Example">
<vaadin-grid-column width="60px" flex-grow="0"></vaadin-grid-column>
<vaadin-grid-column name="First"></vaadin-grid-column>
<vaadin-grid-column name="Last"></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-sorting-filtering-demos-filtering-with-data-provider', function(document) {
const grid = document.querySelector('vaadin-grid');
const columns = grid.querySelectorAll('vaadin-grid-column');
<vaadin-grid-column width="60px" flex-grow="0">
<template class="header">#</template>
<template>[[index]]</template>
</vaadin-grid-column>
grid.size = 200;
<vaadin-grid-column>
<template class="header">
<vaadin-grid-filter aria-label="Fist Name" path="firstName" value="[[_filterFirstName]]">
<vaadin-text-field slot="filter" placeholder="First Name" value="{{_filterFirstName}}" focus-target=""></vaadin-text-field>
</vaadin-grid-filter>
</template>
<template>[[item.firstName]]</template>
</vaadin-grid-column>
grid.dataProvider = function(params, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
var response = JSON.parse(xhr.responseText);
<vaadin-grid-column>
<template class="header">
<vaadin-grid-filter aria-label="Last Name" path="lastName" value="[[_filterLastName]]">
<vaadin-text-field slot="filter" placeholder="Last Name" value="{{_filterLastName}}" focus-target=""></vaadin-text-field>
</vaadin-grid-filter>
</template>
<template>[[item.lastName]]</template>
</vaadin-grid-column>
// Number of items changes after filtering. We need
// to update the grid size based on server response.
grid.size = response.size;
</vaadin-grid>
</template>
<script>
window.addDemoReadyListener('#grid-filtering-demos-filtering-with-data-provider', function(document) {
Polymer({
is: 'x-remote-filtering-example',
callback(response.result);
};
ready: function() {
var grid = this.\$.grid;
var index = params.page * params.pageSize;
var url = 'https://demo.vaadin.com/demo-data/1.0/people?index=' + index + '&count=' + params.pageSize;
grid.size = 200;
// \`params.filters\` format: [{path: 'lastName', direction: 'asc'}, ...];
params.filters.forEach(function(filter) {
url += '&filters[' + filter.path + ']=' + encodeURIComponent(filter.value);
});
grid.dataProvider = function(params, callback) {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
var response = JSON.parse(xhr.responseText);
xhr.open('GET', url, true);
xhr.send();
};
// Number of items changes after filtering. We need
// to update the grid size based on server response.
grid.size = response.size;
columns[0].renderer = function(root, column, model) {
root.textContent = model.index;
};
callback(response.result);
};
columns[0].headerRenderer = function(root) {
root.textContent = '#';
};
var index = params.page * params.pageSize;
var url = 'https://demo.vaadin.com/demo-data/1.0/people?index=' + index + '&count=' + params.pageSize;
columns.forEach(function(column, index) {
// Start from second column
if (index === 0) {
return;
}
// \`params.filters\` format: [{path: 'lastName', direction: 'asc'}, ...];
params.filters.forEach(function(filter) {
url += '&filters[' + filter.path + ']=' + encodeURIComponent(filter.value);
});
const propName = column.getAttribute('name');
xhr.open('GET', url, true);
xhr.send();
};
}
});
column.renderer = function(root, column, model) {
root.textContent = model.item[propName.toLowerCase() + 'Name'];
};
column.headerRenderer = function(root) {
const filter = window.document.createElement('vaadin-grid-filter');
filter.setAttribute('path', propName.toLowerCase() + 'Name');
const textField = window.document.createElement('vaadin-text-field');
textField.setAttribute('slot', 'filter');
textField.setAttribute('focus-target', true);
textField.setAttribute('placeholder', propName + ' Name');
textField.addEventListener('value-changed', function(event) {
filter.value = event.detail.value;
});
filter.appendChild(textField);
root.appendChild(filter);
};
});
&lt;/script>
</dom-module>
});
&lt;/script>
</template>

@@ -155,0 +342,0 @@ </vaadin-demo-snippet>

@@ -25,122 +25,131 @@ import { html } from '@polymer/polymer/lib/utils/html-tag.js';

<template preserve-content="">
<x-pagination></x-pagination>
<dom-module id="x-pagination">
<template preserve-content="">
<style>
#pages {
display: flex;
flex-wrap: wrap;
margin: 20px;
}
<style>
#pages {
display: flex;
flex-wrap: wrap;
margin: 20px;
}
#pages > button {
user-select: none;
padding: 5px;
margin: 0 5px;
border-radius: 10%;
border: 0;
background: transparent;
font: inherit;
outline: none;
cursor: pointer;
}
#pages > button {
user-select: none;
padding: 5px;
margin: 0 5px;
border-radius: 10%;
border: 0;
background: transparent;
font: inherit;
outline: none;
cursor: pointer;
}
#pages > button:hover,
#pages > button:focus {
color: #ccc;
background-color: #eee;
}
#pages > button:hover,
#pages > button:focus {
color: #ccc;
background-color: #eee;
}
#pages > button[selected] {
font-weight: bold;
color: white;
background-color: #ccc;
}
</style>
<x-array-data-provider items="{{items}}"></x-array-data-provider>
#pages > button[selected] {
font-weight: bold;
color: white;
background-color: #ccc;
}
</style>
<vaadin-grid id="grid" page-size="10" height-by-rows="">
<x-array-data-provider></x-array-data-provider>
<vaadin-grid-column>
<template class="header">First Name</template>
<template>
[[item.name.first]]
</template>
</vaadin-grid-column>
<vaadin-grid page-size="10" height-by-rows="">
<vaadin-grid-column name="First"></vaadin-grid-column>
<vaadin-grid-column name="Last"></vaadin-grid-column>
<vaadin-grid-column width="200px" name="Email"></vaadin-grid-column>
</vaadin-grid>
<vaadin-grid-column>
<template class="header">Last Name</template>
<template>
[[item.name.last]]
</template>
</vaadin-grid-column>
<div id="pages"></div>
<vaadin-grid-column width="200px">
<template class="header">Email</template>
<template>
<div>[[item.name.first]].[[item.name.last]]@example.com</div>
</template>
</vaadin-grid-column>
<script>
window.addDemoReadyListener('#grid-pagination-demos-pagination', function(document) {
const grid = document.querySelector('vaadin-grid');
let pages;
</vaadin-grid>
<div id="pages">
<button on-click="_prev">&lt;</button>
<template is="dom-repeat" items="[[pages]]">
<button on-click="_select" selected\$="[[_isSelected(page, item)]]">[[item]]</button>
</template>
<button on-click="_next">&gt;</button>
</div>
</template>
<script>
window.addDemoReadyListener('#grid-pagination-demos-pagination', function(document) {
Polymer({
is: 'x-pagination',
const columns = grid.querySelectorAll('vaadin-grid-column');
properties: {
items: Array,
page: Number,
pages: Array
},
columns.forEach(function(column, index) {
column.headerRenderer = function(root) {
root.textContent = column.getAttribute('name');
};
});
ready: function() {
this.page = 0;
},
columns[0].renderer = function(root, column, model) {
root.textContent = model.item.name.first;
};
observers: ['_itemsChanged(items, page)'],
columns[1].renderer = function(root, column, model) {
root.textContent = model.item.name.last;
};
_isSelected: function(page, item) {
return page === item - 1;
},
columns[2].renderer = function(root, column, model) {
root.textContent = model.item.name.first + '.' + model.item.name.last + '@example.com';
};
_select: function(e) {
this.page = e.model.item - 1;
},
updateItemsFromPage(1);
_next: function() {
this.page = Math.min(this.pages.length - 1, this.page + 1);
},
_prev: function() {
this.page = Math.max(0, this.page - 1);
},
function updateItemsFromPage(page) {
const dataProvider = document.querySelector('x-array-data-provider');
const items = dataProvider.items;
_itemsChanged: function(items, page) {
if (items === undefined || page === undefined) {
return;
}
if (items === undefined || page === undefined) {
return;
}
if (!this.pages) {
this.pages = Array.apply(null, {length: Math.ceil(items.length / this.\$.grid.pageSize)}).map(function(item, index) {
return index + 1;
});
document.querySelectorAll('#pages button').forEach(function(btn) {
if (parseInt(btn.textContent) === page) {
btn.setAttribute('selected', true);
} else {
btn.removeAttribute('selected');
}
});
if (!pages) {
pages = Array.apply(null, {length: Math.ceil(items.length / grid.pageSize)}).map(function(item, index) {
return index + 1;
});
const pagesControl = document.querySelector('#pages');
pagesControl.innerHTML = '';
const prevBtn = window.document.createElement('button');
prevBtn.innerHTML = '&lt;';
prevBtn.addEventListener('click', function() {
const selectedPage = parseInt(pagesControl.querySelector('[selected]').textContent);
updateItemsFromPage(Math.max(0, selectedPage - 1));
});
pagesControl.appendChild(prevBtn);
pages.forEach(function(pageNumber) {
const pageBtn = window.document.createElement('button');
pageBtn.innerHTML = pageNumber;
pageBtn.addEventListener('click', function(e) {
updateItemsFromPage(parseInt(e.target.textContent));
});
if (pageNumber === page) {
pageBtn.setAttribute('selected', true);
}
pagesControl.appendChild(pageBtn);
});
var start = page * this.\$.grid.pageSize;
var end = (page + 1) * this.\$.grid.pageSize;
this.\$.grid.items = items.slice(start, end);
}
});
});
&lt;/script>
</dom-module>
const nextBtn = window.document.createElement('button');
nextBtn.innerHTML = '&gt;';
nextBtn.addEventListener('click', function() {
const selectedPage = parseInt(pagesControl.querySelector('[selected]').textContent);
updateItemsFromPage(Math.min(pages.length - 1, selectedPage + 1));
});
pagesControl.appendChild(nextBtn);
}
var start = page * grid.pageSize;
var end = (page + 1) * grid.pageSize;
grid.items = items.slice(start, end);
}
});
&lt;/script>
</template>

@@ -147,0 +156,0 @@ </vaadin-demo-snippet>

@@ -80,3 +80,3 @@ import { html } from '@polymer/polymer/lib/utils/html-tag.js';

<h3>Toggling Details Without Data Binding</h3>
<h3>Toggling and Rendering Details Using JavaScrtipt</h3>
<p>

@@ -88,69 +88,55 @@ In this example the grid's <code>activeItem</code> property is bound to <code>detailsOpenedItems</code> property.

</p>
<vaadin-demo-snippet id="grid-row-details-demos-toggling-details-without-data-binding">
<vaadin-demo-snippet id="grid-row-details-demos-javascript-toggling-renderer">
<template preserve-content="">
<bind-details-opened-items></bind-details-opened-items>
<dom-module id="bind-details-opened-items">
<template preserve-content="">
<style>
:host {
display: block;
}
<style>
.details {
padding: 10px 30px;
}
</style>
<iron-ajax auto="" url="https://demo.vaadin.com/demo-data/1.0/people?count=200"></iron-ajax>
.details {
display: flex;
font-size: 20px;
}
<vaadin-grid aria-label="Toggling and Rendering Details Using JavaScrtipt Example" size="200">
<vaadin-grid-column width="60px" flex-grow="0"></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
</vaadin-grid>
img {
width: 80px;
height: 80px;
margin: 20px;
}
</style>
<script>
window.addDemoReadyListener('#grid-row-details-demos-javascript-toggling-renderer', function(document) {
const ajax = document.querySelector('iron-ajax');
const grid = document.querySelector('vaadin-grid');
const columns = grid.querySelectorAll('vaadin-grid-column');
<x-data-provider data-provider="{{dataProvider}}"></x-data-provider>
ajax.addEventListener('last-response-changed', function(e) {
grid.items = e.target.lastResponse.result;
});
grid.addEventListener('active-item-changed', function(e) {
grid.detailsOpenedItems = [e.detail.value];
});
<vaadin-grid on-active-item-changed="_onActiveItemChanged" id="grid" aria-label="Details Opened Items Example" data-provider="[[dataProvider]]" size="200">
grid.rowDetailsRenderer = function(root, grid, model) {
root.innerHTML =
'<div class="details">' +
model.item.email + '<br>' + model.item.address.street + '<br>' +
model.item.address.zip + ' ' + model.item.address.city +
'</div>';
};
<template class="row-details">
<div class="details">
<img src="[[item.picture.large]]">
<p>
Hi! My name is [[item.name.first]]!<br>
<small>[[item.email]]</small>
</p>
</div>
</template>
<vaadin-grid-column width="60px" flex-grow="0">
<template class="header">#</template>
<template>[[index]]</template>
</vaadin-grid-column>
<vaadin-grid-column>
<template class="header">First Name</template>
<template>[[item.name.first]]</template>
</vaadin-grid-column>
<vaadin-grid-column>
<template class="header">Last Name</template>
<template>[[item.name.last]]</template>
</vaadin-grid-column>
</vaadin-grid>
</template>
<script>
window.addDemoReadyListener('#grid-row-details-demos-toggling-details-without-data-binding', function(document) {
Polymer({
is: 'bind-details-opened-items',
_onActiveItemChanged: function(e) {
this.\$.grid.detailsOpenedItems = [e.detail.value];
}
});
});
&lt;/script>
</dom-module>
columns[0].renderer = function(root, column, model) {
root.innerHTML = model.index;
};
columns[1].headerRenderer = function(root, column) {
root.innerHTML = 'First Name';
};
columns[1].renderer = function(root, column, model) {
root.innerHTML = model.item.firstName;
};
columns[2].headerRenderer = function(root, column) {
root.innerHTML = 'Last Name';
};
columns[2].renderer = function(root, column, model) {
root.innerHTML = model.item.lastName;
};
});
&lt;/script>
</template>

@@ -157,0 +143,0 @@ </vaadin-demo-snippet>

@@ -29,44 +29,48 @@ import { html } from '@polymer/polymer/lib/utils/html-tag.js';

<template preserve-content="">
<x-selection></x-selection>
<dom-module id="x-selection">
<template preserve-content="">
<x-data-provider data-provider="{{dataProvider}}"></x-data-provider>
<x-data-provider></x-data-provider>
<vaadin-grid aria-label="Selection using Active Item Example" id="grid" data-provider="[[dataProvider]]" active-item="{{activeItem}}" size="200">
<vaadin-grid aria-label="Selection using Active Item Example" id="grid" size="200">
<vaadin-grid-column width="60px" flex-grow="0"></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-selection-demos-selection-using-active-item', function(document) {
const grid = document.querySelector('vaadin-grid');
<vaadin-grid-column width="60px" flex-grow="0">
<template class="header">#</template>
<template>[[index]]</template>
</vaadin-grid-column>
grid.addEventListener('active-item-changed', function(event) {
const item = event.detail.value;
grid.selectedItems = item ? [item] : [];
});
<vaadin-grid-column>
<template class="header">First Name</template>
<template>[[item.name.first]]</template>
</vaadin-grid-column>
const dataProvider = document.querySelector('x-data-provider');
grid.dataProvider = dataProvider.dataProvider;
<vaadin-grid-column>
<template class="header">Last Name</template>
<template>[[item.name.last]]</template>
</vaadin-grid-column>
const columns = document.querySelectorAll('vaadin-grid-column');
</vaadin-grid>
</template>
<script>
window.addDemoReadyListener('#grid-selection-demos-selection-using-active-item', function(document) {
Polymer({
is: 'x-selection',
columns[0].renderer = function(root, column, model) {
root.textContent = model.index;
};
properties: {
activeItem: {
observer: '_activeItemChanged'
}
},
columns[1].renderer = function(root, column, model) {
root.textContent = model.item.name.first;
};
_activeItemChanged: function(item) {
this.\$.grid.selectedItems = item ? [item] : [];
}
});
});
&lt;/script>
</dom-module>
columns[2].renderer = function(root, column, model) {
root.textContent = model.item.name.last;
};
columns[0].headerRenderer = function(root) {
root.textContent = '#';
};
columns[1].headerRenderer = function(root) {
root.textContent = 'First Name';
};
columns[2].headerRenderer = function(root) {
root.textContent = 'Last Name';
};
});
&lt;/script>
</template>

@@ -89,3 +93,2 @@ </vaadin-demo-snippet>

<vaadin-grid aria-label="Selection using Templates Example" data-provider="[[dataProvider]]" size="200">
<vaadin-grid-column width="60px" flex-grow="0">

@@ -111,3 +114,2 @@ <template class="header">#</template>

</vaadin-grid-column>
</vaadin-grid>

@@ -135,29 +137,44 @@ </template>

<template preserve-content="">
<dom-bind>
<template>
<x-array-data-provider></x-array-data-provider>
<x-array-data-provider items="{{items}}"></x-array-data-provider>
<vaadin-grid aria-label="Multi-Selection Example" size="200">
<vaadin-grid-selection-column auto-select=""></vaadin-grid-selection-column>
<vaadin-grid-column width="60px" flex-grow="0"></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-selection-demos-multi-selection-column', function(document) {
const grid = document.querySelector('vaadin-grid');
<vaadin-grid aria-label="Multi-Selection Example" items="[[items]]">
<vaadin-grid-selection-column auto-select="">
</vaadin-grid-selection-column>
const dataProvider = document.querySelector('x-array-data-provider');
grid.items = dataProvider.items;
<vaadin-grid-column width="60px" flex-grow="0">
<template class="header">#</template>
<template>[[index]]</template>
</vaadin-grid-column>
const columns = document.querySelectorAll('vaadin-grid-column');
<vaadin-grid-column>
<template class="header">First Name</template>
<template>[[item.name.first]]</template>
</vaadin-grid-column>
columns[0].renderer = function(root, column, model) {
root.textContent = model.index;
};
<vaadin-grid-column>
<template class="header">Last Name</template>
<template>[[item.name.last]]</template>
</vaadin-grid-column>
columns[1].renderer = function(root, column, model) {
root.textContent = model.item.name.first;
};
</vaadin-grid>
</template>
</dom-bind>
columns[2].renderer = function(root, column, model) {
root.textContent = model.item.name.last;
};
columns[0].headerRenderer = function(root) {
root.textContent = '#';
};
columns[1].headerRenderer = function(root) {
root.textContent = 'First Name';
};
columns[2].headerRenderer = function(root) {
root.textContent = 'Last Name';
};
});
&lt;/script>
</template>

@@ -167,4 +184,2 @@ </vaadin-demo-snippet>

<h3>Custom Select All with Data Provider</h3>

@@ -187,3 +202,2 @@ <p>

<vaadin-grid aria-label="Select All with Data Example" id="grid" data-provider="[[dataProvider]]" inverted\$="[[inverted]]" size="200">
<vaadin-grid-column width="60px" flex-grow="0">

@@ -207,3 +221,2 @@ <template class="header">

</vaadin-grid-column>
</vaadin-grid>

@@ -287,69 +300,86 @@ </template>

<template preserve-content="">
<x-space-action></x-space-action>
<dom-module id="x-space-action">
<template preserve-content="">
<x-data-provider data-provider="{{dataProvider}}"></x-data-provider>
<x-data-provider></x-data-provider>
<vaadin-grid aria-label="Space Key Action Example" id="grid" data-provider="[[dataProvider]]" active-item="{{activeItem}}" size="200">
<vaadin-grid aria-label="Space Key Action Example" size="200">
<vaadin-grid-column></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
<vaadin-grid-column></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-selection-demos-space-key-action-and-click-to-activate', function(document) {
const grid = document.querySelector('vaadin-grid');
<vaadin-grid-column>
<template class="header">Only text contents</template>
<template>
Space activates
</template>
</vaadin-grid-column>
const dataProvider = document.querySelector('x-data-provider');
grid.dataProvider = dataProvider.dataProvider;
<vaadin-grid-column>
<template class="header">Button first child</template>
<template>
<button on-click="_alert">Button</button>
Space does not activate
</template>
</vaadin-grid-column>
const columns = document.querySelectorAll('vaadin-grid-column');
<vaadin-grid-column>
<template class="header">Div first child</template>
<template>
<div on-click="_alert">Div</div>
Space activates
</template>
</vaadin-grid-column>
columns[0].renderer = function(root, column, model) {
root.textContent = 'Space activates';
};
<vaadin-grid-column>
<template class="header">preventDefault for click</template>
<template>
<div on-click="_alertAndPreventDefault">Div with preventDefault</div>
Space does not activate
</template>
</vaadin-grid-column>
columns[1].renderer = function(root, column, model) {
root.innerHTML = '';
const alertBtn = window.document.createElement('button');
alertBtn.textContent = 'Button';
alertBtn.addEventListener('click', function(event) {
alert(event.target.textContent + ' clicked');
});
const textNode = window.document.createTextNode('Space does not activate');
</vaadin-grid>
</template>
<script>
window.addDemoReadyListener('#grid-selection-demos-space-key-action-and-click-to-activate', function(document) {
Polymer({
is: 'x-space-action',
root.appendChild(alertBtn);
root.appendChild(textNode);
};
properties: {
activeItem: {
observer: '_activeItemChanged'
}
},
columns[2].renderer = function(root, column, model) {
root.innerHTML = '';
const alertBlock = window.document.createElement('div');
alertBlock.textContent = 'Div';
alertBlock.addEventListener('click', function(event) {
alert(event.target.textContent + ' clicked');
});
const textNode = window.document.createTextNode('Space activates');
_alert: function(e) {
alert(e.target.textContent + ' clicked');
},
root.appendChild(alertBlock);
root.appendChild(textNode);
};
_alertAndPreventDefault: function(e) {
e.preventDefault();
this._alert(e);
},
columns[3].renderer = function(root, column, model) {
root.innerHTML = '';
const alertBlock = window.document.createElement('div');
alertBlock.textContent = 'Div with preventDefault';
alertBlock.addEventListener('click', function(event) {
event.preventDefault();
alert(event.target.textContent + ' clicked');
});
const textNode = window.document.createTextNode('Space does not activate');
_activeItemChanged: function(item) {
this.\$.grid.selectedItems = item ? [item] : [];
}
});
root.appendChild(alertBlock);
root.appendChild(textNode);
};
columns[0].headerRenderer = function(root) {
root.textContent = 'Only text contents';
};
columns[1].headerRenderer = function(root) {
root.textContent = 'Button first child';
};
columns[2].headerRenderer = function(root) {
root.textContent = 'Div first child';
};
columns[3].headerRenderer = function(root) {
root.textContent = 'preventDefault for click';
};
grid.addEventListener('active-item-changed', function(event) {
const item = event.detail.value;
grid.selectedItems = item ? [item] : [];
});
&lt;/script>
</dom-module>
});
&lt;/script>
</template>

@@ -356,0 +386,0 @@ </vaadin-demo-snippet>

@@ -18,35 +18,56 @@ import { html } from '@polymer/polymer/lib/utils/html-tag.js';

<template preserve-content="">
<dom-bind>
<template>
<iron-ajax auto="" url="https://demo.vaadin.com/demo-data/1.0/people?count=20" handle-as="json" last-response="{{users}}"></iron-ajax>
<iron-ajax url="https://demo.vaadin.com/demo-data/1.0/people?count=20"></iron-ajax>
<vaadin-grid theme="compact" items="[[users.result]]" column-reordering-allowed="" multi-sort="">
<vaadin-grid theme="compact" column-reordering-allowed="" multi-sort="">
<vaadin-grid-selection-column auto-select=""></vaadin-grid-selection-column>
<vaadin-grid-column width="9em"></vaadin-grid-column>
<vaadin-grid-column width="9em"></vaadin-grid-column>
<vaadin-grid-column width="15em" flex-grow="2"></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-lumo-theme-demos-compact', function(document) {
const ajax = document.querySelector('iron-ajax');
<vaadin-grid-selection-column auto-select=""> </vaadin-grid-selection-column>
const grid = document.querySelector('vaadin-grid');
const columns = document.querySelectorAll('vaadin-grid-column');
<vaadin-grid-column width="9em">
<template class="header">
<vaadin-grid-sorter path="firstName">First Name</vaadin-grid-sorter>
</template>
<template>[[item.firstName]]
</template>
</vaadin-grid-column>
ajax.generateRequest();
ajax.addEventListener('last-response-changed', function(e) {
grid.items = e.target.lastResponse.result;
});
<vaadin-grid-column width="9em">
<template class="header">
<vaadin-grid-sorter path="lastName">Last Name</vaadin-grid-sorter>
</template>
<template>[[item.lastName]]</template>
</vaadin-grid-column>
columns[0].renderer = function(root, column, model) {
root.innerHTML = model.item.firstName;
};
columns[0].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'firstName');
sorter.textContent = 'First Name';
root.appendChild(sorter);
};
<vaadin-grid-column width="15em" flex-grow="2">
<template class="header">
<vaadin-grid-sorter path="address.street">Address</vaadin-grid-sorter>
</template>
<template>[[item.address.street]], [[item.address.city]]</template>
</vaadin-grid-column>
columns[1].renderer = function(root, column, model) {
root.innerHTML = model.item.firstName;
};
columns[1].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'lastName');
sorter.textContent = 'Last Name';
root.appendChild(sorter);
};
</vaadin-grid>
</template>
</dom-bind>
columns[2].renderer = function(root, column, model) {
root.innerHTML = model.item.address.street + ', ' + model.item.address.city;
};
columns[2].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'address.streest');
sorter.textContent = 'Address';
root.appendChild(sorter);
};
});
&lt;/script>
</template>

@@ -59,35 +80,57 @@ </vaadin-demo-snippet>

<template preserve-content="">
<dom-bind>
<template>
<iron-ajax auto="" url="https://demo.vaadin.com/demo-data/1.0/people?count=20" handle-as="json" last-response="{{users}}"></iron-ajax>
<iron-ajax url="https://demo.vaadin.com/demo-data/1.0/people?count=20"></iron-ajax>
<vaadin-grid theme="no-border" items="[[users.result]]" column-reordering-allowed="" multi-sort="">
<vaadin-grid theme="no-border" column-reordering-allowed="" multi-sort="">
<vaadin-grid-selection-column auto-select=""></vaadin-grid-selection-column>
<vaadin-grid-column width="9em"></vaadin-grid-column>
<vaadin-grid-column width="9em"></vaadin-grid-column>
<vaadin-grid-column width="15em" flex-grow="2"></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-lumo-theme-demos-bordered', function(document) {
const ajax = document.querySelector('iron-ajax');
<vaadin-grid-selection-column auto-select=""> </vaadin-grid-selection-column>
const grid = document.querySelector('vaadin-grid');
const columns = document.querySelectorAll('vaadin-grid-column');
<vaadin-grid-column width="9em">
<template class="header">
<vaadin-grid-sorter path="firstName">First Name</vaadin-grid-sorter>
</template>
<template>[[item.firstName]]
</template>
</vaadin-grid-column>
<vaadin-grid-column width="9em">
<template class="header">
<vaadin-grid-sorter path="lastName">Last Name</vaadin-grid-sorter>
</template>
<template>[[item.lastName]]</template>
</vaadin-grid-column>
ajax.generateRequest();
ajax.addEventListener('last-response-changed', function(e) {
grid.items = e.target.lastResponse.result;
});
<vaadin-grid-column width="15em" flex-grow="2">
<template class="header">
<vaadin-grid-sorter path="address.street">Address</vaadin-grid-sorter>
</template>
<template>[[item.address.street]], [[item.address.city]]</template>
</vaadin-grid-column>
columns[0].renderer = function(root, column, model) {
root.innerHTML = model.item.firstName;
};
columns[0].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'firstName');
sorter.textContent = 'First Name';
root.appendChild(sorter);
};
</vaadin-grid>
</template>
</dom-bind>
columns[1].renderer = function(root, column, model) {
root.innerHTML = model.item.firstName;
};
columns[1].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'lastName');
sorter.textContent = 'Last Name';
root.appendChild(sorter);
};
columns[2].renderer = function(root, column, model) {
root.innerHTML = model.item.address.street + ', ' + model.item.address.city;
};
columns[2].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'address.streest');
sorter.textContent = 'Address';
root.appendChild(sorter);
};
});
&lt;/script>
</template>

@@ -100,34 +143,57 @@ </vaadin-demo-snippet>

<template preserve-content="">
<dom-bind>
<template>
<iron-ajax auto="" url="https://demo.vaadin.com/demo-data/1.0/people?count=20" handle-as="json" last-response="{{users}}"></iron-ajax>
<iron-ajax url="https://demo.vaadin.com/demo-data/1.0/people?count=20"></iron-ajax>
<vaadin-grid theme="no-row-borders" items="[[users.result]]" column-reordering-allowed="" multi-sort="">
<vaadin-grid theme="no-row-border" column-reordering-allowed="" multi-sort="">
<vaadin-grid-selection-column auto-select=""></vaadin-grid-selection-column>
<vaadin-grid-column width="9em"></vaadin-grid-column>
<vaadin-grid-column width="9em"></vaadin-grid-column>
<vaadin-grid-column width="15em" flex-grow="2"></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-lumo-theme-demos-row-borders', function(document) {
const ajax = document.querySelector('iron-ajax');
<vaadin-grid-selection-column auto-select=""> </vaadin-grid-selection-column>
const grid = document.querySelector('vaadin-grid');
const columns = document.querySelectorAll('vaadin-grid-column');
<vaadin-grid-column width="9em">
<template class="header">
<vaadin-grid-sorter path="firstName">First Name</vaadin-grid-sorter>
</template>
<template>[[item.firstName]]</template>
</vaadin-grid-column>
<vaadin-grid-column width="9em">
<template class="header">
<vaadin-grid-sorter path="lastName">Last Name</vaadin-grid-sorter>
</template>
<template>[[item.lastName]]</template>
</vaadin-grid-column>
ajax.generateRequest();
ajax.addEventListener('last-response-changed', function(e) {
grid.items = e.target.lastResponse.result;
});
<vaadin-grid-column width="15em" flex-grow="2">
<template class="header">
<vaadin-grid-sorter path="address.street">Address</vaadin-grid-sorter>
</template>
<template>[[item.address.street]], [[item.address.city]]</template>
</vaadin-grid-column>
columns[0].renderer = function(root, column, model) {
root.innerHTML = model.item.firstName;
};
columns[0].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'firstName');
sorter.textContent = 'First Name';
root.appendChild(sorter);
};
</vaadin-grid>
</template>
</dom-bind>
columns[1].renderer = function(root, column, model) {
root.innerHTML = model.item.firstName;
};
columns[1].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'lastName');
sorter.textContent = 'Last Name';
root.appendChild(sorter);
};
columns[2].renderer = function(root, column, model) {
root.innerHTML = model.item.address.street + ', ' + model.item.address.city;
};
columns[2].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'address.streest');
sorter.textContent = 'Address';
root.appendChild(sorter);
};
});
&lt;/script>
</template>

@@ -140,35 +206,57 @@ </vaadin-demo-snippet>

<template preserve-content="">
<dom-bind>
<template>
<iron-ajax auto="" url="https://demo.vaadin.com/demo-data/1.0/people?count=20" handle-as="json" last-response="{{users}}"></iron-ajax>
<iron-ajax url="https://demo.vaadin.com/demo-data/1.0/people?count=20"></iron-ajax>
<vaadin-grid theme="column-borders" items="[[users.result]]" column-reordering-allowed="" multi-sort="">
<vaadin-grid theme="column-borders" column-reordering-allowed="" multi-sort="">
<vaadin-grid-selection-column auto-select=""></vaadin-grid-selection-column>
<vaadin-grid-column width="9em"></vaadin-grid-column>
<vaadin-grid-column width="9em"></vaadin-grid-column>
<vaadin-grid-column width="15em" flex-grow="2"></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-lumo-theme-demos-column-borders', function(document) {
const ajax = document.querySelector('iron-ajax');
<vaadin-grid-selection-column auto-select=""> </vaadin-grid-selection-column>
const grid = document.querySelector('vaadin-grid');
const columns = document.querySelectorAll('vaadin-grid-column');
<vaadin-grid-column width="9em">
<template class="header">
<vaadin-grid-sorter path="firstName">First Name</vaadin-grid-sorter>
</template>
<template>[[item.firstName]]
</template>
</vaadin-grid-column>
<vaadin-grid-column width="9em">
<template class="header">
<vaadin-grid-sorter path="lastName">Last Name</vaadin-grid-sorter>
</template>
<template>[[item.lastName]]</template>
</vaadin-grid-column>
ajax.generateRequest();
ajax.addEventListener('last-response-changed', function(e) {
grid.items = e.target.lastResponse.result;
});
<vaadin-grid-column width="15em" flex-grow="2">
<template class="header">
<vaadin-grid-sorter path="address.street">Address</vaadin-grid-sorter>
</template>
<template>[[item.address.street]], [[item.address.city]]</template>
</vaadin-grid-column>
columns[0].renderer = function(root, column, model) {
root.innerHTML = model.item.firstName;
};
columns[0].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'firstName');
sorter.textContent = 'First Name';
root.appendChild(sorter);
};
</vaadin-grid>
</template>
</dom-bind>
columns[1].renderer = function(root, column, model) {
root.innerHTML = model.item.firstName;
};
columns[1].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'lastName');
sorter.textContent = 'Last Name';
root.appendChild(sorter);
};
columns[2].renderer = function(root, column, model) {
root.innerHTML = model.item.address.street + ', ' + model.item.address.city;
};
columns[2].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'address.streest');
sorter.textContent = 'Address';
root.appendChild(sorter);
};
});
&lt;/script>
</template>

@@ -181,35 +269,57 @@ </vaadin-demo-snippet>

<template preserve-content="">
<dom-bind>
<template>
<iron-ajax auto="" url="https://demo.vaadin.com/demo-data/1.0/people?count=20" handle-as="json" last-response="{{users}}"></iron-ajax>
<iron-ajax url="https://demo.vaadin.com/demo-data/1.0/people?count=20"></iron-ajax>
<vaadin-grid theme="row-stripes" items="[[users.result]]" column-reordering-allowed="" multi-sort="">
<vaadin-grid theme="row-stripes" column-reordering-allowed="" multi-sort="">
<vaadin-grid-selection-column auto-select=""></vaadin-grid-selection-column>
<vaadin-grid-column width="9em"></vaadin-grid-column>
<vaadin-grid-column width="9em"></vaadin-grid-column>
<vaadin-grid-column width="15em" flex-grow="2"></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-lumo-theme-demos-row-stripes', function(document) {
const ajax = document.querySelector('iron-ajax');
<vaadin-grid-selection-column auto-select=""> </vaadin-grid-selection-column>
const grid = document.querySelector('vaadin-grid');
const columns = document.querySelectorAll('vaadin-grid-column');
<vaadin-grid-column width="9em">
<template class="header">
<vaadin-grid-sorter path="firstName">First Name</vaadin-grid-sorter>
</template>
<template>[[item.firstName]]
</template>
</vaadin-grid-column>
<vaadin-grid-column width="9em">
<template class="header">
<vaadin-grid-sorter path="lastName">Last Name</vaadin-grid-sorter>
</template>
<template>[[item.lastName]]</template>
</vaadin-grid-column>
ajax.generateRequest();
ajax.addEventListener('last-response-changed', function(e) {
grid.items = e.target.lastResponse.result;
});
<vaadin-grid-column width="15em" flex-grow="2">
<template class="header">
<vaadin-grid-sorter path="address.street">Address</vaadin-grid-sorter>
</template>
<template>[[item.address.street]], [[item.address.city]]</template>
</vaadin-grid-column>
columns[0].renderer = function(root, column, model) {
root.innerHTML = model.item.firstName;
};
columns[0].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'firstName');
sorter.textContent = 'First Name';
root.appendChild(sorter);
};
</vaadin-grid>
</template>
</dom-bind>
columns[1].renderer = function(root, column, model) {
root.innerHTML = model.item.firstName;
};
columns[1].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'lastName');
sorter.textContent = 'Last Name';
root.appendChild(sorter);
};
columns[2].renderer = function(root, column, model) {
root.innerHTML = model.item.address.street + ', ' + model.item.address.city;
};
columns[2].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'address.streest');
sorter.textContent = 'Address';
root.appendChild(sorter);
};
});
&lt;/script>
</template>

@@ -223,35 +333,57 @@ </vaadin-demo-snippet>

<template preserve-content="">
<dom-bind>
<template>
<iron-ajax auto="" url="https://demo.vaadin.com/demo-data/1.0/people?count=20" handle-as="json" last-response="{{users}}"></iron-ajax>
<iron-ajax url="https://demo.vaadin.com/demo-data/1.0/people?count=20"></iron-ajax>
<vaadin-grid theme="wrap-cell-content" items="[[users.result]]" column-reordering-allowed="" multi-sort="">
<vaadin-grid theme="wrap-cell-content" column-reordering-allowed="" multi-sort="">
<vaadin-grid-selection-column auto-select=""></vaadin-grid-selection-column>
<vaadin-grid-column width="9em"></vaadin-grid-column>
<vaadin-grid-column width="9em"></vaadin-grid-column>
<vaadin-grid-column width="15em" flex-grow="2"></vaadin-grid-column>
</vaadin-grid>
<script>
window.addDemoReadyListener('#grid-lumo-theme-demos-wrap-cell-content', function(document) {
const ajax = document.querySelector('iron-ajax');
<vaadin-grid-selection-column auto-select=""> </vaadin-grid-selection-column>
const grid = document.querySelector('vaadin-grid');
const columns = document.querySelectorAll('vaadin-grid-column');
<vaadin-grid-column width="9em">
<template class="header">
<vaadin-grid-sorter path="firstName">First Name</vaadin-grid-sorter>
</template>
<template>[[item.firstName]]
</template>
</vaadin-grid-column>
<vaadin-grid-column width="9em">
<template class="header">
<vaadin-grid-sorter path="lastName">Last Name</vaadin-grid-sorter>
</template>
<template>[[item.lastName]]</template>
</vaadin-grid-column>
ajax.generateRequest();
ajax.addEventListener('last-response-changed', function(e) {
grid.items = e.target.lastResponse.result;
});
<vaadin-grid-column width="15em">
<template class="header">
<vaadin-grid-sorter path="address.street">Address</vaadin-grid-sorter>
</template>
<template>[[item.address.street]], [[item.address.city]]</template>
</vaadin-grid-column>
columns[0].renderer = function(root, column, model) {
root.innerHTML = model.item.firstName;
};
columns[0].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'firstName');
sorter.textContent = 'First Name';
root.appendChild(sorter);
};
</vaadin-grid>
</template>
</dom-bind>
columns[1].renderer = function(root, column, model) {
root.innerHTML = model.item.firstName;
};
columns[1].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'lastName');
sorter.textContent = 'Last Name';
root.appendChild(sorter);
};
columns[2].renderer = function(root, column, model) {
root.innerHTML = model.item.address.street + ', ' + model.item.address.city;
};
columns[2].headerRenderer = function(root, column) {
root.innerHTML = '';
const sorter = window.document.createElement('vaadin-grid-sorter');
sorter.setAttribute('path', 'address.streest');
sorter.textContent = 'Address';
root.appendChild(sorter);
};
});
&lt;/script>
</template>

@@ -258,0 +390,0 @@ </vaadin-demo-snippet>

@@ -9,3 +9,2 @@ {

"web-components",
"gwt",
"grid",

@@ -20,3 +19,3 @@ "datagrid",

"name": "@vaadin/vaadin-grid",
"version": "5.1.0",
"version": "5.2.0-alpha1",
"main": "vaadin-grid.js",

@@ -30,6 +29,6 @@ "author": "Vaadin Ltd",

"@polymer/polymer": "^3.0.0",
"@polymer/iron-resizable-behavior": "^3.0.0-pre.18",
"@polymer/iron-scroll-target-behavior": "^3.0.0-pre.18",
"@polymer/iron-a11y-keys-behavior": "^3.0.0-pre.18",
"@polymer/iron-a11y-announcer": "^3.0.0-pre.18",
"@polymer/iron-resizable-behavior": "^3.0.0-pre.15",
"@polymer/iron-scroll-target-behavior": "^3.0.0-pre.15",
"@polymer/iron-a11y-keys-behavior": "^3.0.0-pre.15",
"@polymer/iron-a11y-announcer": "^3.0.0-pre.15",
"@vaadin/vaadin-themable-mixin": "^1.2.1",

@@ -47,19 +46,20 @@ "@vaadin/vaadin-checkbox": "^2.2.1",

"supports-color": "3.1.2",
"type-detect": "1.0.0"
"type-detect": "1.0.0",
"@webcomponents/webcomponentsjs": "2.0.0-beta.2"
},
"devDependencies": {
"@webcomponents/webcomponentsjs": "^2.0.0",
"wct-browser-legacy": "^1.0.1",
"@polymer/iron-test-helpers": "^3.0.0-pre.18",
"@polymer/paper-input": "^3.0.0-pre.18",
"@polymer/paper-checkbox": "^3.0.0-pre.18",
"@polymer/iron-demo-helpers": "^3.0.0-pre.18",
"@polymer/iron-flex-layout": "^3.0.0-pre.18",
"@polymer/iron-image": "^3.0.0-pre.18",
"@polymer/paper-slider": "^3.0.0-pre.18",
"@polymer/iron-media-query": "^3.0.0-pre.18",
"@polymer/iron-component-page": "^3.0.0-pre.18",
"@polymer/iron-ajax": "^3.0.0-pre.18",
"@polymer/app-localize-behavior": "^3.0.0-pre.18",
"@polymer/iron-list": "^3.0.0-pre.18",
"@webcomponents/webcomponentsjs": "^2.0.0-beta.2",
"wct-browser-legacy": "^0.0.1-pre.11",
"@polymer/iron-test-helpers": "^3.0.0-pre.15",
"@polymer/paper-input": "^3.0.0-pre.15",
"@polymer/paper-checkbox": "^3.0.0-pre.15",
"@polymer/iron-demo-helpers": "^3.0.0-pre.15",
"@polymer/iron-flex-layout": "^3.0.0-pre.15",
"@polymer/iron-image": "^3.0.0-pre.15",
"@polymer/paper-slider": "^3.0.0-pre.15",
"@polymer/iron-media-query": "^3.0.0-pre.15",
"@polymer/iron-component-page": "^3.0.0-pre.15",
"@polymer/iron-ajax": "^3.0.0-pre.15",
"@polymer/app-localize-behavior": "^3.0.0-pre.15",
"@polymer/iron-list": "^3.0.0-pre.15",
"@vaadin/vaadin-demo-helpers": "^2.0.2",

@@ -66,0 +66,0 @@ "@vaadin/vaadin-button": "^2.1.0"

@@ -17,7 +17,7 @@ /**

_a11yGetHeaderRowCount(_columnTree) {
return _columnTree.filter(level => level.some(col => col._headerTemplate)).length;
return _columnTree.filter(level => level.some(col => col._headerTemplate || col.headerRenderer)).length;
}
_a11yGetFooterRowCount(_columnTree) {
return _columnTree.filter(level => level.some(col => col._headerTemplate)).length;
return _columnTree.filter(level => level.some(col => col._headerTemplate || col.headerRenderer)).length;
}

@@ -24,0 +24,0 @@

@@ -62,3 +62,5 @@ /**

if (!cellContentHasFocus && !this._isFocusable(e.target)) {
this.dispatchEvent(new CustomEvent('cell-activate', {detail: {model: cell._instance}}));
this.dispatchEvent(new CustomEvent('cell-activate', {detail: {
model: this.__getRowModel(cell.parentElement)
}}));
}

@@ -65,0 +67,0 @@ }

@@ -76,3 +76,21 @@ /**

_grid: Object
_grid: Object,
/**
* Custom function for rendering the header content.
* Receives two arguments:
*
* - `root` The header cell content DOM element. Append your content to it.
* - `column` The `<vaadin-grid-column>` element.
*/
headerRenderer: Function,
/**
* Custom function for rendering the footer content.
* Receives two arguments:
*
* - `root` The footer cell content DOM element. Append your content to it.
* - `column` The `<vaadin-grid-column>` element.
*/
footerRenderer: Function
};

@@ -88,5 +106,5 @@ }

'_lastFrozenChanged(_lastFrozen)',
'_stampBodyTemplate(_bodyTemplate, _cells, _cells.*)',
'_stampHeaderTemplate(_headerTemplate, _headerCell)',
'_stampFooterTemplate(_footerTemplate, _footerCell)',
'_setBodyTemplateOrRenderer(_bodyTemplate, renderer, _cells, _cells.*)',
'_setHeaderTemplateOrRenderer(_headerTemplate, headerRenderer, _headerCell)',
'_setFooterTemplateOrRenderer(_footerTemplate, footerRenderer, _footerCell)',
'_resizableChanged(resizable, _headerCell)',

@@ -197,5 +215,17 @@ '_reorderStatusChanged(_reorderStatus, _headerCell, _footerCell, _cells.*)',

__stampColumnTemplate(template, cells) {
__setColumnTemplateOrRenderer(template, renderer, cells) {
if (template && renderer) {
throw new Error('You should only use either a renderer or a template');
}
cells.forEach(cell => {
if (cell._template !== template) {
const model = {item: cell.parentElement._item, index: cell.parentElement.index};
if (renderer) {
cell._renderer = renderer;
if (model.item || renderer === this.headerRenderer || renderer === this.footerRenderer) {
renderer.call(this, cell._content, this, model);
}
} else if (cell._template !== template) {
cell._template = template;

@@ -207,5 +237,5 @@

cell._instance = inst;
inst.index = cell.parentElement.index; // TODO: _index
inst.item = cell.parentElement._item;
if (model.item) {
cell._instance.setProperties(model);
}
}

@@ -215,11 +245,11 @@ });

_stampBodyTemplate(template, cells, splices) {
if (template && cells) {
this.__stampColumnTemplate(template, cells);
_setBodyTemplateOrRenderer(template, renderer, cells, splices) {
if ((template || renderer) && cells) {
this.__setColumnTemplateOrRenderer(template, renderer, cells);
}
}
_stampHeaderTemplate(headerTemplate, headerCell) {
if (headerTemplate && headerCell) {
this.__stampColumnTemplate(headerTemplate, [headerCell]);
_setHeaderTemplateOrRenderer(headerTemplate, headerRenderer, headerCell) {
if ((headerTemplate || headerRenderer) && headerCell) {
this.__setColumnTemplateOrRenderer(headerTemplate, headerRenderer, [headerCell]);
headerCell.parentElement.hidden = false;

@@ -229,5 +259,5 @@ }

_stampFooterTemplate(footerTemplate, footerCell) {
if (footerTemplate && footerCell) {
this.__stampColumnTemplate(footerTemplate, [footerCell]);
_setFooterTemplateOrRenderer(footerTemplate, footerRenderer, footerCell) {
if ((footerTemplate || footerRenderer) && footerCell) {
this.__setColumnTemplateOrRenderer(footerTemplate, footerRenderer, [footerCell]);
footerCell.parentElement.hidden = false;

@@ -390,2 +420,18 @@ }

/**
* Custom function for rendering the cell content.
* Receives three arguments:
*
* - `root` The cell content DOM element. Append your content to it.
* - `column` The `<vaadin-grid-column>` element.
* - `model` The object with the properties related with
* the rendered item, contains:
* - `model.index` The index of the item.
* - `model.item` The item.
*
* **NOTE:** The renderer callback can be called multiple times
* with the previous content.
*/
renderer: Function,
_bodyTemplate: {

@@ -392,0 +438,0 @@ type: Object

@@ -75,2 +75,3 @@ /**

connectedCallback() {
super.connectedCallback();
this._connected = true;

@@ -77,0 +78,0 @@ }

@@ -417,3 +417,5 @@ /**

} else {
this.dispatchEvent(new CustomEvent('cell-activate', {detail: {model: cell._instance}}));
this.dispatchEvent(new CustomEvent('cell-activate', {detail: {
model: this.__getRowModel(cell.parentElement)
}}));
}

@@ -420,0 +422,0 @@ }

@@ -28,2 +28,18 @@ /**

/**
* Custom function for rendering the content of the row details.
* Receives three arguments:
*
* - `root` The row details content DOM element. Append your content to it.
* - `grid` The `<vaadin-grid>` element.
* - `model` The object with the properties related with
* the rendered item, contains:
* - `model.index` The index of the item.
* - `model.item` The item.
*
* **NOTE:** The renderer callback can be called multiple times
* with the previous content.
*/
rowDetailsRenderer: Function,
_detailsCells: {

@@ -37,14 +53,16 @@ type: Array,

return [
'_detailsOpenedItemsChanged(detailsOpenedItems.*, dataProvider, _rowDetailsTemplate, _physicalCountVal)',
'_rowDetailsTemplateChanged(_rowDetailsTemplate)'
'_detailsOpenedItemsChanged(detailsOpenedItems.*, dataProvider, _physicalCountVal, _rowDetailsTemplate, rowDetailsRenderer)',
'_rowDetailsTemplateOrRendererChanged(_rowDetailsTemplate, rowDetailsRenderer)'
];
}
_rowDetailsTemplateChanged(rowDetailsTemplate) {
if (rowDetailsTemplate) {
var templatizer = new Templatizer();
templatizer._grid = this;
templatizer.dataHost = this.dataHost;
templatizer.template = rowDetailsTemplate;
rowDetailsTemplate.templatizer = templatizer;
_rowDetailsTemplateOrRendererChanged(rowDetailsTemplate, rowDetailsRenderer) {
if (rowDetailsTemplate || rowDetailsRenderer) {
if (rowDetailsTemplate) {
var templatizer = new Templatizer();
templatizer._grid = this;
templatizer.dataHost = this.dataHost;
templatizer.template = rowDetailsTemplate;
rowDetailsTemplate.templatizer = templatizer;
}

@@ -66,4 +84,8 @@ if (this._columnTree) {

_detailsOpenedItemsChanged(changeRecord, dataProvider, rowDetailsTemplate, physicalCount) {
if (dataProvider === undefined || !rowDetailsTemplate) {
_detailsOpenedItemsChanged(changeRecord, dataProvider, physicalCount, rowDetailsTemplate, rowDetailsRenderer) {
if (rowDetailsTemplate && rowDetailsRenderer) {
throw new Error('You should only use either a renderer or a template for row details');
}
if (dataProvider === undefined || !rowDetailsTemplate && !rowDetailsRenderer) {
return;

@@ -97,3 +119,3 @@ }

const detailsHidden = !this._isDetailsOpened(item);
if (cell && (!cell._instance || cell.hidden !== detailsHidden)) {
if (cell && (!cell._instance && !cell._renderer || cell.hidden !== detailsHidden)) {
cell.hidden = detailsHidden;

@@ -103,3 +125,7 @@ if (detailsHidden) {

} else {
if (!cell._instance) {
if (this.rowDetailsRenderer) {
cell._renderer = this.rowDetailsRenderer;
cell._renderer.call(this, cell._content, this, {index: row.index, item: item});
this._updateItem(row, item);
} else if (!cell._instance) {
// Stamp the template

@@ -106,0 +132,0 @@ cell._instance = this._rowDetailsTemplate.templatizer.createInstance();

@@ -77,3 +77,3 @@ /**

Array.from(this.$.items.children).forEach(row => {
this._toggleRowSelected(row, this._isSelected(row._item));
this._updateItem(row, row._item);
});

@@ -80,0 +80,0 @@ }

@@ -13,2 +13,3 @@ /**

const $_documentContainer = document.createElement('template');
$_documentContainer.setAttribute('style', 'display: none;');

@@ -15,0 +16,0 @@ $_documentContainer.innerHTML = `<custom-style>

const $_documentContainer = document.createElement('template');
$_documentContainer.setAttribute('style', 'display: none;');

@@ -3,0 +4,0 @@ $_documentContainer.innerHTML = `<dom-module id="vaadin-grid-styles">

@@ -14,2 +14,3 @@ /**

const $_documentContainer = document.createElement('template');
$_documentContainer.setAttribute('style', 'display: none;');

@@ -16,0 +17,0 @@ $_documentContainer.innerHTML = `<custom-style>

@@ -42,12 +42,61 @@ /**

/**
* `<vaadin-grid>` is a free, high quality data grid / data table Polymer element.
*
* `<vaadin-grid>` is a free, high quality data grid / data table Polymer element. The content of the
* the grid can be populated in two ways: imperatively by using renderer callback function and
* declaratively by using Polymer's Templates.
*
* ### Quick Start
*
* Start with an assigning an array to the [`items`](#/elements/vaadin-grid#property-items) property to visualize your data.
*
* Use the [`<vaadin-grid-column>`](#/elements/vaadin-grid-column) element to configure the grid columns.
* `vaadin-grid-column` element provides you with three types of `renderer` callback functions: `headerRenderer`,
* `renderer` and `footerRenderer`.
*
* Then assign an array to the [`items`](#/elements/vaadin-grid#property-items) property to visualize your data.
* Each of those renderer functions provides `root`, `column`, `model` arguments when applicable.
* Generate DOM content, append it to the `root` element and control the state
* of the host element by accessing `column`. Before generating new content,
* users are able to check if there is already content in `root` for reusing it.
*
* #### Example:
* ```html
* <vaadin-grid>
* <vaadin-grid-column></vaadin-grid-column>
* <vaadin-grid-column></vaadin-grid-column>
* <vaadin-grid-column></vaadin-grid-column>
* </vaadin-grid>
* ```
* ```js
* const grid = document.querySelector('vaadin-grid');
* grid.items = [{'name': 'John', 'surname': 'Lennon', 'role': 'singer'},
* {'name': 'Ringo', 'surname': 'Starr', 'role': 'drums'}];
*
* const columns = grid.querySelectorAll('vaadin-grid-column');
*
* columns[0].headerRenderer = function(root) {
* root.textContent = 'Name';
* };
* columns[0].renderer = function(root, column, model) {
* root.textContent = model.item.name;
* };
*
* columns[1].headerRenderer = function(root) {
* root.textContent = 'Surname';
* };
* columns[1].renderer = function(root, column, model) {
* root.textContent = model.item.surname;
* };
*
* columns[2].headerRenderer = function(root) {
* root.textContent = 'Role';
* };
* columns[2].renderer = function(root, column, model) {
* root.textContent = model.item.role;
* };
* ```
*
* Alternatively, the content can be provided with Polymer's Templates:
*
* #### Example:
* ```html
* <vaadin-grid items='[{"name": "John", "surname": "Lennon", "role": "singer"},

@@ -248,3 +297,3 @@ * {"name": "Ringo", "surname": "Starr", "role": "drums"}]'>

static get version() {
return '5.1.0';
return '5.2.0-alpha1';
}

@@ -417,3 +466,3 @@

if (index === columns.length - 1 && this._rowDetailsTemplate) {
if (index === columns.length - 1 && (this._rowDetailsTemplate || this.rowDetailsRenderer)) {
// Add details cell as last cell to body rows

@@ -524,17 +573,25 @@ this._detailsCells = this._detailsCells || [];

row._item = item;
const model = this.__getRowModel(row);
this._a11yUpdateRowDetailsOpened(row, model.detailsOpened);
this._toggleAttribute('selected', model.selected, row);
this._a11yUpdateRowSelected(row, model.selected);
this._a11yUpdateRowLevel(row, model.level);
this._toggleAttribute('expanded', model.expanded, row);
if (this._rowDetailsTemplate || this.rowDetailsRenderer) {
this._toggleDetailsCell(row, item);
}
Array.from(row.children).forEach(cell => {
if (cell._instance) {
cell._instance.setProperties({
item,
index: row.index
});
if (cell._renderer) {
const owner = cell._column || this;
cell._renderer.call(owner, cell._content, owner, model);
} else if (cell._instance) {
cell._instance.__detailsOpened__ = model.detailsOpened;
cell._instance.__selected__ = model.selected;
cell._instance.__level__ = model.level;
cell._instance.__expanded__ = model.expanded;
cell._instance.setProperties(model);
}
});
this._toggleRowSelected(row, this._isSelected(item));
this._toggleRowDetailsOpened(row, this._rowDetailsTemplate && this._isDetailsOpened(item));
this._toggleRowExpanded(row, this._isExpanded(item));
this._updateRowLevel(row, this._getIndexLevel(row.index));
if (this._rowDetailsTemplate) {
this._toggleDetailsCell(row, item);
}

@@ -550,43 +607,2 @@ this._debouncerUpdateHeights = Debouncer.debounce(this._debouncerUpdateHeights,

_toggleRowDetailsOpened(row, detailsOpened) {
Array.from(row.children).forEach(cell => {
if (cell._instance) {
cell._instance.__detailsOpened__ = detailsOpened;
cell._instance.detailsOpened = detailsOpened;
}
});
this._a11yUpdateRowDetailsOpened(row, detailsOpened);
}
_toggleRowSelected(row, selected) {
Array.from(row.children).forEach(cell => {
if (cell._instance) {
cell._instance.__selected__ = selected;
cell._instance.selected = selected;
}
});
this._toggleAttribute('selected', selected, row);
this._a11yUpdateRowSelected(row, selected);
}
_updateRowLevel(row, level) {
Array.from(row.children).forEach(cell => {
if (cell._instance) {
cell._instance.__level__ = level;
cell._instance.level = level;
}
});
this._a11yUpdateRowLevel(row, level);
}
_toggleRowExpanded(row, expanded) {
Array.from(row.children).forEach(cell => {
if (cell._instance) {
cell._instance.__expanded__ = expanded;
cell._instance.expanded = expanded;
}
});
this._toggleAttribute('expanded', expanded, row);
}
_resizeHandler() {

@@ -632,2 +648,14 @@ this._updateDetailsCellHeights();

}
__getRowModel(row) {
return {
index: row.index,
item: row._item,
level: this._getIndexLevel(row.index),
expanded: this._isExpanded(row._item),
selected: this._isSelected(row._item),
detailsOpened:
(this._rowDetailsTemplate || this.rowDetailsRenderer) && this._isDetailsOpened(row._item)
};
}
}

@@ -634,0 +662,0 @@

@@ -33,3 +33,4 @@ const isPolymer2 = document.querySelector('script[src*="wct-browser-legacy"]') === null;

'style-scope.html',
'templates.html'
'templates.html',
'renderers.html'
];

@@ -36,0 +37,0 @@

import '@vaadin/vaadin-lumo-styles/color.js';
const $_documentContainer = document.createElement('template');
$_documentContainer.setAttribute('style', 'display: none;');

@@ -4,0 +5,0 @@ $_documentContainer.innerHTML = `<dom-module id="lumo-grid-sorter" theme-for="vaadin-grid-sorter">

@@ -9,2 +9,3 @@ import '@vaadin/vaadin-lumo-styles/color.js';

const $_documentContainer = document.createElement('template');
$_documentContainer.setAttribute('style', 'display: none;');

@@ -11,0 +12,0 @@ $_documentContainer.innerHTML = `<dom-module id="lumo-grid" theme-for="vaadin-grid">

import '@vaadin/vaadin-lumo-styles/color.js';
import '@vaadin/vaadin-lumo-styles/spacing.js';
const $_documentContainer = document.createElement('template');
$_documentContainer.setAttribute('style', 'display: none;');

@@ -5,0 +6,0 @@ $_documentContainer.innerHTML = `<dom-module id="lumo-grid-tree-toggle" theme-for="vaadin-grid-tree-toggle">

import '@vaadin/vaadin-material-styles/color.js';
import '@vaadin/vaadin-material-styles/font-icons.js';
const $_documentContainer = document.createElement('template');
$_documentContainer.setAttribute('style', 'display: none;');

@@ -5,0 +6,0 @@ $_documentContainer.innerHTML = `<dom-module id="material-grid-sorter" theme-for="vaadin-grid-sorter">

import '@vaadin/vaadin-material-styles/color.js';
import '@vaadin/vaadin-material-styles/typography.js';
const $_documentContainer = document.createElement('template');
$_documentContainer.setAttribute('style', 'display: none;');

@@ -5,0 +6,0 @@ $_documentContainer.innerHTML = `<dom-module id="material-grid" theme-for="vaadin-grid">

@@ -5,2 +5,3 @@ import '@vaadin/vaadin-material-styles/color.js';

const $_documentContainer = document.createElement('template');
$_documentContainer.setAttribute('style', 'display: none;');

@@ -7,0 +8,0 @@ $_documentContainer.innerHTML = `<dom-module id="material-grid-tree-toggle" theme-for="vaadin-grid-tree-toggle">

Sorry, the diff of this file is too big to display

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc