This page shows how to get started with Wijmo WebComponents.
Introduction
This sample introduces Beta version of the Wijmo WebComponents v1 interop , which exposes
Wijmo controls as
WebComponents.
Wijmo web components allows you to declaratively add Wijmo controls to HTML page,
and manipulate them as usual DOM elements, without the use of any additional
framework. Some browsers that still don't fully support WebComponents standards
may require some additional polyfills.
If you are not familiar with WebComponents, here's the
good introduction to this technology.
The key aspects of the current state of the Wijmo WebComponents implementation:
Wijmo "top-level" web components that represent Wijmo controls,
like wjc-flex-grid component representing FlexGrid control,
are inherited from the corresponding control classes. For example, WjcFlexGrid
component class extends FlexGrid control class.
This also means that the base Wijmo Control class extends the
HTMLElement class when Wijmo is used in the "WebComponents mode".
Child components which are complementary to top-level components, like
wjc-flex-grid-column components that define FlexGrid columns,
function as wrappers over Wijmo classes they represent. Child components
are directly inherited from the HTMLElement class, and the
underlying Wijmo class instance is accessible via the special
control property of the component.
Wijmo class properties can be defined using attributes on the component
element. When attribute value changes, the corresponding Wijmo class property
is updated accordingly. Changing the class property value doesn't entail changing
of the corresponding attribute value. This probably can be changed in the future,
but right now we have no a decision on whether it's necessary.
JavaScript code can subscribe handlers to Wijmo control events using
native Element.addEventListener('event', handler) method.
Wijmo components don't use Shadow DOM now. This will be addressed in the
future versions of the interop. One of the challenges here is that
Wijmo allows deep customization of its control's parts via CSS, whereas
the goal of Shadow DOM is to prevent it. There are new proposals to
the Shadow DOM specification that can mitigate this limitation. We continue
to keep track the changes. For now, Wijmo web components and their parts
can be customized in the same way as ordinary Wijmo controls,
using global CSS.
With Wijmo web components interop, you can be declaratively add controls
to HTML markup, as shown in this example:
Enable Wijmo "WebComponents mode" using the following assignment in the root html
page, which must be performed before any Wijmo module has been loaded:
These imports will cause the modules to globally register comprising
web components using the window.customElements.define(...) method.
(Not applicable to this sample!) If you want to use Wijmo WebComponents
interop as a global module, you need to add the wijmo.webcomponents.js file
located in the dist/interop/webcomponents folder of Wijmo download zip to
the root html page using the <script> tag:
Property values can be specified using corresponding attributes defined on the
Wijmo web component element.
The following rules should be considered:
Attribute names should be in the dash delimited format, for example
first-day-of-week should be used to specify a value for the
firstDayOfWeek property.
Only simple type properties can be specified as attributes.
For enum type properties the enum member names can be used,
for example selection-mode="Day".
Because attribute values are always strings, Wijmo web components
perform an appropriate value conversion before assigning the value
to the corresponding property.
The following example shows a wjc-calendar web component
with the specified properties of different types.
In addition to "top-level" web components representing Wijmo Controls,
there are also child components that help to declaratively customize
its parent component's setup. For example, you can specify a list
of FlexGrid columns using the wjc-flex-grid-column components,
or define FlexChart series using the wjc-flex-chart-series
child components.
Child components must be immediate children of their parent component.
The example below demonstrates:
wjc-flex-grid component with child wjc-flex-grid-column
components defining a list of grid columns, and a wjc-flex-grid-filter
child component that applies columns filter to the grid.
wjc-flex-chart component with child wjc-flex-chart-series
components defining chart's series, and wjc-flex-chart-axis
child components that customize chart's X and Y axes.
let chData = dataSvc.getData(dataSvc.countries.length);
let gridWithChildren = document.getElementById('gridWithChildren');
gridWithChildren.itemsSource = chData;
let chartWithChildren = document.getElementById('chartWithChildren');
chartWithChildren.itemsSource = chData;
Result (live):
Referencing and using in code
You can find a Wijmo web component element using conventional DOM api
like the document.getElementById method. After that you can access
Wijmo specific API of this element by following the next rules:
For top level components representing Wijmo Controls all the
control's API is available right on the element, because such
components are directly inherited from the corresponding control class.
For example, you can use the following code to assign data to
the FlexGrid web component:
For child components accompanying Wijmo Control components you should use
special control property to get a reference to the underlying Wijmo
object, because Wijmo child components function as wrappers around the
Wijmo classes they represent. For example, this code can be used to specify
filter column list for the FlexGridFilter web component:
The following example attaches wjc-group-panel component to the
wjc-flex-grid component, as well as defines filter column list
for the wjc-flex-grid-filter component.
// Find grid element in the DOM tree
let gridRef = document.getElementById('gridRef');
// The element is also a FlexGrid instance (inherited from FlexGrid),
// so we can use FlexGrid api on the element, e.g. to assign its data
// source.
gridRef.itemsSource = dataSvc.getData(100);
// Find group panel element in the DOM tree
let panelRef = document.getElementById('panelRef');
// and attach it to the grid:
panelRef.grid = gridRef;
// Find wjc-flex-grid-filter component in the DOM tree
let filterRef = document.getElementById('filterRef');
// and specify the filterColumns property value of its
// underlying FlexGridFilter object
filterRef.control.filterColumns = ['country', 'date'];
Result (live):
Events
You can subscribe to Wijmo specific events using conventional
addEventListener method, as you do with the native HTML
elements. The event name should be specified in the dash delimited
format, for example value-changed for the native Wijmo
valueChanged event.
For example, you can subscribe to the InputNumber.valueChanged
event of the corresponding web component using the code like this:
document.querySelector('wjc-input-number').addEventListener('value-changed', (e) => {
alert(`New value is ${e.target.value}`);
});
Wijmo components trigger events of the
CustomEvent
type. There are two key properties of the event object that can be used in
the event handler:
target - references the web component that triggered the event.
detail - holds event arguments of the corresponding Wijmo event.
For example, for the
FlexGrid.formatItem event the CustomEvent.detail
property will contain an object of the
FormatItemEventArgs type.
Note that Wijmo web components representing Wijmo Controls inherit two different
versions of the addEventListener methods from the two base classes -
wijmo.Control implements its own version of this method, and it also
inherit this method from the base HTMLElement class. Because these
two incarnations of this method have different signatures, Wijmo web components
are capable to differentiate them and call an appropriate implementation of this method.
The following example uses value-changed event of the
wjc-input-number and wjc-linear-gauge
components to synchronize their values. It also uses wjc-flex-grid's format-item
event to customize cell content of the Active column.
// InputNumber and LinearGauge synchronized using valueChanged event
let inpNumEvents = document.getElementById('inpNumEvents');
let gaugeEvents = document.getElementById('gaugeEvents');
inpNumEvents.addEventListener('value-changed', (e: CustomEvent) => {
// CustomEvent.target references the component where event occurred
gaugeEvents.value = (e.target).value;
});
gaugeEvents.addEventListener('value-changed', (e: CustomEvent) => {
inpNumEvents.value = (e.target).value;
});
// FlexGrid's Active column formatted using formatItem event
let gridEvents = document.getElementById('gridEvents');
gridEvents.itemsSource = dataSvc.getData(100);
gridEvents.addEventListener('format-item', (e: CustomEvent) => {
// CustomEvent.detail contains corresponding Wijmo event arguments
let args = e.detail,
grid = args.panel.grid;
if (args.panel === grid.cells &&
grid.columns[args.col].binding === 'active' &&
!args.range.equals(grid.editRange)) {
args.cell.innerHTML = grid.getCellData(args.row, args.col, false) ? 'Yes' : 'No';
}
});
Result (live):
Creating programmatically
You can operate with Wijmo web component elements using standard DOM API,
in the same way as you do it with native HTML element. Specifically, you can:
Create a Wijmo component using document.createElement method,
for example document.createElement('wjc-flex-grid').
Add, move and remove elements to/from the DOM tree using the methods
like document.appendChild, document.insertBefore and
document.removeChild.
The same is true for Wijmo child components, for example you can
add, remove and reorder grid columns by adding/removing/reordering
wjc-flex-grid-column elements in their parent
wjc-flex-grid element.
This sample creates a FlexGrid with columns and column filters programmatically,
by creating corresponding Wijmo web components and adding them to the appropriate
places of the DOM tree.
// Find placeholder element
let placeHolder = document.getElementById('gridProg');
// Create FlexGrid web component
let gridProg = document.createElement('wjc-flex-grid');
// Add grid to DOM
placeHolder.appendChild(gridProg);
// Create Column web component
let countryCol = document.createElement('wjc-flex-grid-column');
// add child to parent before assigning its properties
gridProg.appendChild(countryCol);
countryCol.control.binding = 'country';
countryCol.control.header = 'Country';
countryCol.control.width = '*';
// Create Column web component
let downloadsCol = document.createElement('wjc-flex-grid-column');
// add child to parent before assigning its properties
gridProg.appendChild(downloadsCol);
downloadsCol.control.binding = 'downloads';
downloadsCol.control.header = 'Downloads';
// Create FlexGridFilter web component
let filter = document.createElement('wjc-flex-grid-filter');
// add child to parent before assigning its properties
gridProg.appendChild(filter);
filter.filterColumns = ['country'];
// Set grid data
(gridProg).itemsSource = dataSvc.getData(100);