README
Skinny Widgets
Skinnable component set based on W3C standards compilant technologies.
Allows you to develop ui abstract code and easily switch between layouts without rewriting the code.
If you are looking for web components based data grid library check out gridy-grid project.
Note: starting from 0.2.0 Skinny Widgets is modular with divding to npm packages so you can find one-theme-only bundles for themes:
jquery sk-jquery-bundle antd sk-antd-bundle default sk-default-bundle
or go completely without bundles installing only elements you use. Like with the following command:
npm install sk-input sk-input-jquery
Here is the list of bundled elements:
sk-input sk-button sk-select sk-switch sk-checkbox sk-datepicker sk-alert sk-dialog sk-tabs sk-accordion sk-navbar sk-menu sk-app sk-tree sk-form sk-spinner
Examples
To see examples run http server to serve files
npm start
open one of examples in browser, e.g. http://127.0.0.1:8080/examples/compat/browser-compatible.html
For more examples check skinny-widgets-samples project.
Configuration
All-Inclusive Elements autoloading
If you don't need to do advanced configurations you can enable sk elements autoloading by adding sk-auto and sk-theme-{theme} html or body element class. Elements autoregister will run at the end of skinny-widgets-bundle.js loading so to start using skinny-widgets components you will have to just add one script and one attribute to your document.
<html class="sk-auto sk-theme-jquery">
<script src="/node_modules/skinny-widgets/dist/sk-compat-bundle.js"></script>
<sk-button theme="jquery">Hello</sk-button>
</html>
Template preload can be disabled by adding class sk-auto-notpl.
Modular loading
Skinny Widgets are developed with ESM and WHATWG modules in mind, so you can just import element classes and define them as Custom Elements.
<sk-config
id="configEl"
theme="jquery"
base-path="/node_modules/skinny-widgets/src"
></sk-config>
<sk-button id="myButton" button-type="primary">
MyButton
</sk-button>
<script type="module">
import { SkConfig } from '/node_modules/sk-core/src/sk-config.js';
import { SkButton } from '/node_modules/sk-button/src/sk-button.js';
customElements.define('sk-config', SkConfig);
customElements.define('sk-button', SkButton);
myButton.addEventListener('click', (event) => {
alert("I'm clicked !");
});
</script>
Some of them may rely on 3rd-party libraries and can be plugged at runtime or sometimes not.
As browsers still doesn't support relative dependency paths and importmaps you may need some code to resolve dependency on dateutils and other possible libraries.
<script defer src="/node_modules/es-module-shims/dist/es-module-shims.js"></script>
<script type="importmap-shim">
{
"imports": {
"dateutils": "/node_modules/dateutils/src/global.js",
"dateutils/": "/node_modules/dateutils/"
}
}
</script>
<script type="module-shim">
import { SkDatePicker } from '/node_modules/sk-datepicker/src/sk-datepicker.js';
customElements.define('sk-datepicker', SkDatePicker);
</script>
<sk-datepicker theme="antd" id="myDatePicker" value="12/25/2019"></sk-datepicker>
Although you're still free to use static scripts with bundle that exposes skinny web components into global scope with transpilation for older browsers. You may still need to load polyfills before bundle. Check examples for more info.
<script src="/dist/sk-compat-bundle.js"></script>
<script type="module">
customElements.define('sk-config', SkConfig);
customElements.define('sk-button', SkButton);
</script>
sk-config element is acts as common configuration host service, elements tries to find it on connectCallback and get necessary configurations, so you don't have to repeat params for every element. If config-sl attribute is not specified config element it search by configEl window property, then document is queried by sk-config tag name.
<sk-config
styles='{"default.css": "/node_modules/sk-theme-default/default.css"}'
theme="jquery"
base-path="/node_modules/skinny-widgets/src"
></sk-config>
You can override config search selector for every element by defining config-sl attribute:
<sk-config
id="alternativeConfigSelector"
theme="jquery"
base-path="/node_modules/skinny-widgets/src"
></sk-config>
<sk-input config-sl="#alternativeConfigSelector"></sk-input>
Attributes
theme - one of supported themes: e.g. 'antd' or 'jquery' (default: 'default')
base-path - path to sources and resources root, (default: '/node_modules/skinny-widgets/src/')
tpl-path - override url for template loading (only individual)
theme-path - url prefix lo toad resources (css, styles) from, starting from 0.2.0, defaults to ${basePath}/theme/${themeName} if not set or overriden by element impl
styles - set of style definitions used by elements as Object { 'name': 'path' }. Commonly styles are mounted into shadow root by given path. This allows to provide CSS isolation features saving performance with file browser cashing. Theme code has style file defaults. This files are that are needed to be applied to every component. With theme-path you can override the path to all them at once. Style attribute allows to completely change url for this files to load. This doesn't affect files attached by link tags in templates except they have higher override priority. When set to "false" disables theme styles automount into element's shadow root (default: undefined)
use-shadow-root - specifies if Shadow Root encapsulation is enabled for elements (default: 'true')
lang - locale code, currently used only for datepicker (default: 'en_US')
i18n - object with translation values that can be used with this.tr() method, e.g.
this.tr('Hello, {{ username }}', { username: 'John'});
to render this, element must have attribute set at i18n='{"Hello, {{ username }}": "Hallo, {{ username }}"}'. If it doesn't, original rendered string is returned.
Placeholders also can be passed with {0} format, in this case values will be taken from the rest of method arguments.
This values can be also set via element's instance property with the same name.
reflective - element auto re-render on external events, currently sk-config attrs change (default: true)
gen-ids - generate path based ids if absent (default: 'false')
rd-var-render - render option that switches template variable rendering modes between native template with simplified handlebars like support, original handlebars library usage (from window.Handlebars), same named external function call binded to renderer (you can assign own renderer class with method render(tpl, data) to it's _templateEngine property) search in window global or no variable rendering (default: 'true')
rd-cache - defines whether template cache is enabled or not (default: 'true')
rd-cache-global - allows to store and reuse templates in document body (default: 'true')
rd-tpl-fmt - defines template tag format, 'hadlebars' can be specified to generate templates with script tag instead of native template tag (default: undefined)
rd-own - creates own instance of renderer
tpl-vars - template prerendering variables override, e.g. tpl-vars='{"themePath": "../"}' will override themePath for template rendering context
jsonpath-dri-cn - use alternative jsonpath driver class e.g. "JsonPathPlusDriver"
jsonpath-dri-path use alternative jsonpath driver path e.g. "/node_modules/sk-core/src/impl/jsonpath/jsonpath-plus-driver.js"
st-store - store element's state to external storage otherwise if needed it's placed in element's attribute 'state', supported values: 'session', (default: undefined)
For session store elements are identified by cid that is set from specified id or generated (from dom path by default), so you will have to avoid id duplicates for this case.
log-lv - enabled log levels, possible values are "info", "debug", "warn", "error". Levels do not include each other, so enabling debug will not take every other label but only allow messages logged with this level (default: "info,error,warn")
log-t - log target can be "memory" to agregate messages in logger's property or "console" to use browser's console, you also can define your own overriding SkElement.createLogger() method, (default: not set === "console")
attr-plugins enable plugin attributes scan, additional definitions like: plg-${name}-cn="MyPlugin" plg-${name}-path="/my-plugin.js" will enable automatic plugin loading and binding
Configure with Json Object
You can specify json object with the same camel-cased config options. If
<script>
window.skConfig = {
theme: 'jquery'
};
</script>
<sk-config></sk-config>
You can control
<body class="sk-config-el-individual"></body>
possible values are:
sk-config-el-global - one global sk-config element will be created if absent and shared between elements
sk-config-el-individual - one global sk-config element will be created if absent and shared between elements
sk-config-el-disabled - sk-config elements will not be appended to document, although it will be present as this.configEl element's class property
Skins
antd - and.design framework styles are used for layout
jquery - web components styled for jquery-ui
default - web components and standard native browser elements and technologies are used for layout
Templates preload
http/2+ allows to do request multiplexing that means a lot of smaller requests to the same host are better than big blocking requests to multiple hosts. But if you think you still need to load all in one bundle, you can use aggregated template bundles loaded with js or included to page by server. You can rely on sk-auto template preloading or do manual preload.
<script>
const loadTemplates = async () => {
const response = await fetch('node_modules/skinny-widgets/dist/antd.templates.html')
.then(response => response.text())
.then(text => document.body.insertAdjacentHTML('beforeend', text));
};
loadTemplates();
</script>
Widgets
sk-button
<sk-button id="myButton" button-type="primary">
MyButton
</sk-button>
slots
default (not specified) - contents inside button
label - the same as label
template
id: SkButtonTpl
sk-input
<sk-input id="myInput1" value="foobar"></sk-input>
attributes
value - value syncronized with internal native element
disabled - disabled attribute syncronized with internal native element
list - datalist attribute for input
slots
default (not specified) - draws label for input
label - draws label for input
<sk-input id="myInput1">
<span slot="label">Some Label</span>
</sk-input>
template
id: SkInputTpl
sk-checkbox
slots
default (not specified) - draws label for input
label - draws label for input
attributes
value - value syncronized with internal native element
disabled - disabled attribute syncronized with internal native element
<sk-checkbox theme="antd" base-path="/node_modules/skinny-widgets/src" id="myCheckbox"></sk-checkbox>
template
id: SkCheckboxTpl
sk-datepicker
<sk-datepicker base-path="/node_modules/skinny-widgets/src" id="myDatePicker" value="12/25/2019"></sk-datepicker>
slots
default (not specified) - draws label for input
label - draws label for input
attributes
open - present if datepicker calendar widget is currently opened (for native datepicker only represents focus state)
fmt - date value format (default: 'm/d/Y')
- {Date} d [01-31]
- {Short_Day_Name} D [Su, Mo, Tu, We, Th, Fr, Sa]
- {Date} j [1-31]
- {Full_day_name} l [Sunday, Monday, Tuesday, Wednesday, Thursday, Friday, Saturday]
- {Week_day_number} w 0=Sunday, 1=Monday, 2=Tuesday etc...
- {Nth_day_of_year} z [1-365] except leap years
- {Full_month_name} F [January, February, ...]
- {Month_number} m [01-12]
- {Month_name_stripped_to_three_letters} M [Jan, Feb, ...]
- {Month_number} n [1-12]
- {Days_in_current_month} t [28-31]
- {Full_year} Y [1900, ...]
- {Last_two_digits_of_a_year} y [01-99]
- {Time_postfix} a [am|pm]
- {Time_postfix} A [AM|PM]
- {Hours_in_12h_format} g [1-12]
- {Hours_in_24h_format} G [0-23]
- {Hour_in_12h_format_with_padding} h [01-12]
- {Hours_in_24h_format_with_padding} H [00-23]
- {Minutes_with_padding} i [00-59]
- {Seconds_with_padding} s [00-59]
- {Timezone} Z 2 for GMT+2
template
id: SkDatePickerTpl
sk-alert
<sk-alert type="error">Error ! Error !</sk-alert>
slots
default (not specified) - alert contents
attributes
closable - close button
template
id: SkAlertTpl
sk-dialog
<sk-button theme="antd" base-path="/node_modules/skinny-widgets/src" id="myButton" button-type="primary">
<span slot="label">Show Dialog</span>
</sk-button>
<sk-dialog theme="antd" base-path="/node_modules/skinny-widgets/src" id="myDialog" title="Some Title" type="confirm">
Hello Dialog !
</sk-dialog>
<script type="module">
import { SkButton } from '/node_modules/sk-button/src/sk-button.js';
import { SkDialog } from '/node_modules/sk-dialog/src/sk-dialog.js';
customElements.define('sk-button', SkButton);
customElements.define('sk-dialog', SkDialog);
myButton.addEventListener('click', (event) => {
myDialog.open();
});
myDialog.onconfirm = function(event) {
console.log('confirmed');
this.close();
};
myDialog.oncancel = function(event) {
console.log('cancelled');
this.close();
};
</script>
As most of sk-elements sk-dialog by default renders it's contents inside Shadow DOM. So in case you want access some its data you will have to to extend SkDialog class, implement getters that will access internals and return values and register class as new Custom Element. It is quite easy and gives a better solution for code structure;)
slots
label - dialog window title
attributes
to-body - sometimes browser says it doesn't support dialogs in shadow dom (certainly with polyfill), but you can force it remount to body, although beaware, styles will be remounted too. Remounting will flush all event bindings added with .addEventListener() on internals so you will have to bind, everything at least on dialog instance or with dynamic late binding in addition components must be able to work property with rerendering, e.g. dump and restore state to externals or attributes.
open - identifies dialog state, you can control it (open or close) by adding or removing this attribute
dialog-tn - dialog element tag name (default: 'dialog'), set to 'div' in case you want to have no-dialog element dialog
Extending dialog actions
Sk Dialog allows you to use your own action buttons that are binded to methods and events by action (for sk-button) or data-action (for button) attributes. You can provided needed set of buttons by overriding dialog footer template.
<sk-dialog id="myDialog" title="Some Title" type="confirm" to-body>
myDialog
<sk-input id="skInput" sk-required></sk-input>
<sk-checkbox id="skCheckbox" sk-required></sk-checkbox>
<sk-switch id="skSwitch" sk-required></sk-switch>
<template id="SkDialogFooterTpl">
<div>
<sk-button action="cancel" type="button">Cancel</sk-button>
<sk-button action="save" type="button" button-type="primary">Save</sk-button>
</div>
</template>
</sk-dialog>
<script type="module">
import { SkDialog } from '/node-modules/sk-dialog/src/sk-dialog.js';
customElements.define('sk-dialog', SkDialog);
myDialog.addEventListener('confirm', function(event) {
console.log('confirmed');
});
myDialog.addEventListener('yo', function(event) {
console.log('yoyo');
});
myDialog.oncancel = function (event) {
console.log('cancelled');
this.close();
};
</script>
Note: Template ids must be prefixed according to constructor/class name, e.g. in case you are doing dialog with, extending SkDialog class your footer template fill be search by id "YourClassNameFooterTpl".
template
id: SkDialogTpl, SkDialogFooterTpl
sk-tabs
<sk-config
theme="antd"
base-path="/node_modules/skinny-widgets/src"
lang="ru"
></sk-config>
<sk-tabs id="tabs">
<sk-tab title="foo">
some foo tab contents
</sk-tab>
<sk-tab title="bar">
some bar tab contents
</sk-tab>
<sk-tab title="baz">
some baz tab contents
</sk-tab>
</sk-tabs>
attributes
disabled - all tabs disabled
template
id: SkTabTpl
sk-accordion
<sk-config
theme="antd"
base-path="/node_modules/skinny-widgets/src"
></sk-config>
<sk-accordion id="accordion">
<sk-tab title="foo">
some foo tab contents
</sk-tab>
<sk-tab title="bar">
some bar tab contents
</sk-tab>
<sk-tab title="baz">
some baz tab contents
</sk-tab>
</sk-accordion>
attributes
disabled - all tabs disabled
mono - open only one tab at once
template
id: SkAccordionTpl
sk-navbar
<sk-config
theme="antd"
base-path="/node_modules/skinny-widgets/src"
></sk-config>
<sk-navbar>
Nabar Contents
</sk-navbar>
you can enable panel and specify template for contents as path or using caching mechanics
<sk-navbar id="navbar1" align="top" panel panel-tpl-path="fakepath">
Some top Contents
Bar
<template id="SkNavbarPanelTpl">
<a href="/foo">foo</a>
<a href="/bar">bar</a>
</template>
</sk-navbar>
attributes
open - identifies and controls if navbar is open
align - can be "right", "left", "buttom" and "top" to define where navbar is nested (default: "left")
auto-open - enables auto open and close on mouse move close to navbar side
panel - show panel
panel-tpl-path - specify custom tpl path for panel (e.g. panel-tpl-path="/panel.tpl.html"), if not specified nothing is rendered
sticky - by default panels are sticky, but you can disable this by setting it to "false"
clength - contents pane width or height
template
id: SkNavbarTpl
sk-select
<sk-config
styles='{"antd.css": "/node_modules/sk-theme-antd/antd.min.css"}'
theme="antd"
base-path="/node_modules/skinny-widgets/src"
lang="ru"
id="skConfig"
></sk-config>
<sk-select id="skSelect">
<option value="default">default</option>
<option value="antd">antd</option>
<option value="jquery">jquery</option>
</sk-select>
<script type="module">
import { SkConfig } from '/node_modules/sk-core/src/sk-config.js';
import { SkSelect } from '/node_modules/sk-select/src/sk-select.js';
customElements.define('sk-config', SkConfig);
customElements.define('sk-select', SkSelect);
skSelect.value = skConfig.getAttribute('theme');
skSelect.addEventListener('change', (event) => {
skConfig.setAttribute('theme', event.target.value);
}, false);
</script>
attributes
multiple - sk-select draws multiple selection widget and represent selected options as comma-separated list.
value-type - for multiselect native - show only first selected value as native elements, selectOptions prop will give you all of them, default -- comma-separated list of values.
slots
label - draws label for select
template
id: SkSelectTpl
sk-switch
<sk-config
styles='{"antd.css": "/node_modules/sk-theme-antd/antd.min.css"}'
theme="antd"
base-path="/node_modules/skinny-widgets/src"
></sk-config>
<sk-switch id="mySwitch" checked value="11"></sk-switch>
<script type="module">
import { SkConfig } from '/node_modules/sk-core/src/sk-config.js';
import { SkSwitch } from '/node_modules/sk-switch/src/sk-switch.js';
customElements.define('sk-config', SkConfig);
customElements.define('sk-switch', SkSwitch);
</script>
slots
default (not specified) - draws label for input
label - draws label for input
<sk-switch id="mySwitch1">Some Label</sk-switch>
template
id: SkSwitchTpl
sk-tree
<sk-tree link-tpl-str='<a href="?categoryId={{ id }}">{{ name }}</a>' tree-data='[{"id": 1, "name": "category1", "parentId": 0}, {"id": 2, "name": "category2", "parentId": 0}, {"id": 3, "name": "category11", "parentId": 1}, {"id": 4, "name": "category111", "parentId": 3}]'></sk-tree>
attributes
expanded - "false" value collapses the tree and renders it as collapsible, "true" renders as expanded but collapsible
selected-id - id of the element that's branch will be forced to be extended
link-tpl-str - inline template for each item contents
item-tpl-path - external template path for item
root-tn - root tag name (default: 'ul')
item-tn - item tag name (default: 'li')
root-cn - class name for root (default: 'sk-tree-root')
item-cn - class name for item (default: 'sk-tree-item')
branch-cn - class name for branch (default: 'sk-tree-has-child')
selectable - enable item by click selection forwarded to value attribute
template
id: SkTreeTpl, SkTreeItemTpl
sk-spinner
<sk-config
styles='{"antd.css": "/node_modules/sk-theme-antd/antd.min.css"}'
theme="antd"
base-path="/node_modules/skinny-widgets/src"
lang="ru"
></sk-config>
<sk-button id="skButton" button-type="primary">
<span slot="label">Show Dialog</span>
</sk-button>
<sk-spinner id="skSpinner"></sk-spinner>
<script type="module">
import { SkSpinner } from '/node_modules/sk-spinner/src/sk-spinner.js';
import { SkButton } from '/node_modules/sk-button/src/sk-button.js';
customElements.define('sk-spinner', SkSpinner);
customElements.define('sk-button', SkButton);
skButton.addEventListener('click', (event) => {
skSpinner.dispatchEvent(new CustomEvent('toggle'));
});
</script>
template
id: SkSpinnerTpl
sk-form
sk-form sends it's fields as FormData (multipart request), attributes are the same as for form element type
to have data submission working sk-form must have sk-button with type="submit" inside
supported form element types:
sk-input, sk-checkbox, sk-select, sk-datepicker, input, textarea
if novalidate attribute is not set validation is performed on submit
if validation is not passed forminvalid event is emitted with info in event.detail.errors
if validation successfull formvalid event is emitted and form attempts to send data
it throws formsubmitsuccess event on 200 or any success response
and formsubmiterror
request/response data is stored in event.detail.request callback argument field
<sk-form action="/submit" method="POST" id="myForm">
<span slot="fields">
<sk-input name="firstName" id="formInput1">
<span slot="label">First Name</span>
</sk-input>
<sk-input name="secondName" id="formInput2">
<span slot="label">Second Name</span>
</sk-input>
<sk-input name="address" id="formInput3">
<span slot="label">Address</span>
</sk-input>
<sk-checkbox name="isSingle" id="formCheckbox"><span slot="label">Single</span></sk-checkbox>
<sk-select name="gender" id="formSelect">
<option value="male">Male</option>
<option value="female">Female</option>
</sk-select>
<sk-button id="formButton" type="submit" button-type="primary">
<span slot="label">Submit</span>
</sk-button>
</span>
</sk-form>
<script type="module">
import { SkButton } from '/node_modules/sk-button/src/sk-button.js';
import { SkInput } from '/node_modules/sk-input/src/sk-input.js';
import { SkSelect } from '/node_modules/sk-select/src/sk-select.js';
import { SkForm } from '/node_modules/sk-form/src/sk-form.js';
import { SkCheckbox } from '/node_modules/sk-checkbox/src/sk-checkbox.js';
customElements.define('sk-button', SkButton);
customElements.define('sk-input', SkInput);
customElements.define('sk-select', SkSelect);
customElements.define('sk-form', SkForm);
customElements.define('sk-checkbox', SkCheckbox);
myForm.addEventListener('formsubmitsuccess', (event) => {
console.log('form submit success handled', event);
});
myForm.addEventListener('formsubmiterror', (event) => {
console.log('form submit error handled', event);
});
</script>
attributes
action, method - same as for the form element
enctype - same as for form element, with additional application/json type support
response-validation - response validation integration method, set as "fasle" to disable
Action buttons
while bootstrap process sk-form lookups for all internal button and sk-button elements with and bind them with callback by name or as firing events (see similar sk-dialog functionality for examples). So you can extend form with your own button triggered logic.
Field Validation
You can bind custom validation function for every field:
<script>
function validateFirstName(el) {
if (el.value == '1') {
return true;
} else {
return 'Wrong value';
}
}
</script>
<sk-input name="firstName" id="formInput1" form-validation="validateFirstName" form-validation-msg="{'someError': 'This field has some error'}">First Name</sk-input>
form-validation attribute specifies validation function name, it can be binded to global (window) or field class. Validation function returns error message or validation key to load from form-validation-msg or true in case value is valid.
To enable validation labels display use validation-label attribute of an element or sk-form, use value "disabled" to force it's switch off.
no-live-validation attribute disables field revalidation on input
Backend validation
You can use response-validation sk-form attribute or define 'validateResponse' method to provide post-submit validator for cases when backend can return validation result json. Xml Http Request Event will be passed as argument of this method and formsubmitsuccess or formsubmiterror events will be triggered depending on validator function execution result. As it is called with form context you can use form methods or resources to indicate error.
<sk-config
theme="jquery"
base-path="./node_modules/skinny-widgets/src"
lang="ru"
id="myConfig"
></sk-config>
<script type="module">
import { SkCheckbox } from './node_modules/sk-checkbox/src/sk-checkbox.js';
import { SkButton } from './node_modules/sk-button/src/sk-button.js';
import { SkConfig } from './node_modules/sk-core/src/sk-config.js';
import { SkSelect } from './node_modules/sk-select/src/sk-select.js';
import { SkInput } from './node_modules/sk-input/src/sk-input.js';
import { SkForm } from './node_modules/sk-form/src/sk-form.js';
customElements.define('sk-config', SkConfig);
customElements.define('sk-checkbox', SkCheckbox);
customElements.define('sk-button', SkButton);
customElements.define('sk-select', SkSelect);
customElements.define('sk-input', SkInput);
customElements.define('sk-form', SkForm);
myForm.addEventListener('formsubmitsuccess', (event) => {
console.log('form submit success handled', event);
});
myForm.addEventListener('formsubmiterror', (event) => {
console.log('form submit success handled', event);
});
myForm.responseValidator = function(event) {
let errors = event.response.fieldErrors;
if (errors) {
for (let fieldName of Object.keys(errors)) {
let field = this.querySelector(`[name='${fieldName}']`);
if (field) {
let message = '';
if (Array.isArray(errors[fieldName])) {
message = errors[fieldName].join(' ');
} else {
message = errors[fieldName];
}
field.setCustomValidity(message);
this.impl.renderFieldInvalid(field);
}
}
}
// remove error indication from valid fields
let fields = this.impl.queryFields();
for (let field of fields) {
let fieldName = field.getAttribute('name');
if (fieldName && ! errors[fieldName]) {
this.impl.renderFieldValid(field);
}
}
};
</script>
<sk-form id="myForm" action="/submit" method="POST" response-validation="responseValidator" validation-label>
<sk-select id="skSelect2" name="skSelect2" multiple>
<option value="apple">Apple</option>
<option value="banana">Banana</option>
<option value="lemon">Lemon</option>
</sk-select>
<sk-checkbox id="myCheckbox" name="myCheckbox">Checkbox</sk-checkbox>
<sk-input id="myInput" name="myInput">My Input</sk-input>
<sk-button id="formButton" type="submit" button-type="primary">Submit</sk-button>
</sk-form>
where response is like:
{
"fieldErrors": {
"myInput": [
"Hey, your input is invalid !"
]
},
"result": "error"
}
template
id: SkFormTpl
Sk Validators
Sk Widgets has a set of validators you can combine with native and your custom validators. At least they have no 'initially invalid' behaviour. Validators are added to elements as attributes just as Validation API validators, but they have sk- prefix in names.
sk-required - checks that field is required.
sk-min - checks that field not less than value. The number of symbols is checked in case of string.
sk-max - checks that field is greater than value. The number of symbols is checked in case of string.
sk-email - checks that field is matches email validation regex.
sk-pattern - checks that field is matches provided validation regex.
<sk-input name="firstName" id="formInput1" sk-pattern="^[A-Za-z]+