diff --git a/packages/ajax/stories/index.stories.mdx b/packages/ajax/stories/index.stories.mdx
index 53bee561f..4648fd231 100644
--- a/packages/ajax/stories/index.stories.mdx
+++ b/packages/ajax/stories/index.stories.mdx
@@ -56,7 +56,120 @@ npm i --save @lion/ajax
import { ajax, AjaxClass } from '@lion/ajax';
```
-## Cancelable Request
+### Performing requests
+
+Performing a `GET` request:
+
+
+ {html`
+
+ `}
+
+
+```js
+ajax
+ .get('./packages/ajax/stories/data.json')
+ .then(response => {
+ console.log(response.data);
+ })
+ .catch(error => {
+ console.log(error);
+ });
+```
+
+To post data to the server, pass the data as the second argument in the `POST` request:
+
+```js
+const body = {
+ ant: {
+ type: "insect",
+ limbs: 6,
+ }
+};
+
+ajax
+ .post('zooApi/animals/addAnimal', body)
+ .then(response => {
+ console.log(`POST successful: ${response.status} ${response.statusText}`);
+ })
+ .catch(error => {
+ console.log(error);
+ });
+```
+
+## Configuration
+
+### JSON prefix
+
+The called API might add a JSON prefix to the response in order to prevent hijacking.
+The prefix renders the string syntactically invalid as a script so that it cannot be hijacked.
+This prefix should be stripped before parsing the string as JSON.
+Pass the prefix with the `jsonPrefix` option.
+
+```js
+const myAjax = AjaxClass.getNewInstance({ jsonPrefix: ")]}'," });
+myAjax
+ .get('./packages/ajax/stories/data.json')
+ .then(response => {
+ console.log(response.data);
+ })
+ .catch(error => {
+ console.log(error);
+ });
+```
+
+### Additional headers
+
+Add additional headers to the requests with the `headers` option.
+
+
+ {html`
+
+ `}
+
+
+```js
+const myAjax = AjaxClass.getNewInstance({ headers: { 'X-CUSTOM-HEADER': 'SOME-HEADER-VALUE' } });
+myAjax
+ .get('./packages/ajax/stories/data.json')
+ .then(response => {
+ console.log(response);
+ })
+ .catch(error => {
+ console.log(error);
+ });
+```
+
+When executing the request above, check the Network tab in the Browser's dev tools and look for the Request Header on the GET call.
+
+### Cancelable Request
It is possible to make an Ajax request cancelable, and then call `cancel()` to make the request provide a custom error once fired.
@@ -100,7 +213,7 @@ myAjax
});
```
-## Cancel concurrent requests
+### Cancel concurrent requests
You can cancel concurrent requests with the `cancelPreviousOnNewRequest` option.
diff --git a/packages/checkbox-group/stories/index.stories.mdx b/packages/checkbox-group/stories/index.stories.mdx
index f5397e413..2e847fe6a 100644
--- a/packages/checkbox-group/stories/index.stories.mdx
+++ b/packages/checkbox-group/stories/index.stories.mdx
@@ -237,13 +237,12 @@ Below is a more advanced validator on the group that evaluates the children chec
{() => {
loadDefaultFeedbackMessages();
class HasMinTwoChecked extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'HasMinTwoChecked';
- }
execute(value) {
return value.length < 2;
}
+ static get validatorName() {
+ return 'HasMinTwoChecked';
+ }
static async getMessage() {
return 'You need to select at least 2 values.';
}
@@ -284,15 +283,15 @@ import { Required, Validator, loadDefaultFeedbackMessages } from '@lion/validate
loadDefaultFeedbackMessages();
class HasMinTwoChecked extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'HasMinTwoChecked';
- }
execute(value) {
return value.length < 2;
}
+ static get validatorName() {
+ return 'HasMinTwoChecked';
+ }
+
static async getMessage() {
return 'You need to select at least 2 values.';
}
diff --git a/packages/field/test-suites/FormatMixin.suite.js b/packages/field/test-suites/FormatMixin.suite.js
index 6514529d9..1f19b6b7f 100644
--- a/packages/field/test-suites/FormatMixin.suite.js
+++ b/packages/field/test-suites/FormatMixin.suite.js
@@ -338,9 +338,8 @@ export function runFormatMixinSuite(customConfig) {
// that set hasError back to false when the user input is mimicked.
const AlwaysInvalid = class extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'AlwaysInvalid';
+ static get validatorName() {
+ return 'AlwaysInvalid';
}
execute() {
diff --git a/packages/field/test/lion-field.test.js b/packages/field/test/lion-field.test.js
index 99c8c8bc5..b45fe156f 100644
--- a/packages/field/test/lion-field.test.js
+++ b/packages/field/test/lion-field.test.js
@@ -298,9 +298,8 @@ describe('', () => {
it('should conditionally show error', async () => {
const HasX = class extends Validator {
- constructor() {
- super();
- this.name = 'HasX';
+ static get validatorName() {
+ return 'HasX';
}
execute(value) {
@@ -412,9 +411,8 @@ describe('', () => {
it('will only update formattedValue when valid on `user-input-changed`', async () => {
const formatterSpy = sinon.spy(value => `foo: ${value}`);
const Bar = class extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'Bar';
+ static get validatorName() {
+ return 'Bar';
}
execute(value) {
diff --git a/packages/fieldset/src/FormElementsHaveNoError.js b/packages/fieldset/src/FormElementsHaveNoError.js
index 70d133de0..d9cc17646 100644
--- a/packages/fieldset/src/FormElementsHaveNoError.js
+++ b/packages/fieldset/src/FormElementsHaveNoError.js
@@ -1,9 +1,8 @@
import { Validator } from '@lion/validate';
export class FormElementsHaveNoError extends Validator {
- constructor() {
- super();
- this.name = 'FormElementsHaveNoError';
+ static get validatorName() {
+ return 'FormElementsHaveNoError';
}
// eslint-disable-next-line class-methods-use-this
diff --git a/packages/fieldset/test/lion-fieldset.test.js b/packages/fieldset/test/lion-fieldset.test.js
index 3690bbeb6..13207bf9e 100644
--- a/packages/fieldset/test/lion-fieldset.test.js
+++ b/packages/fieldset/test/lion-fieldset.test.js
@@ -343,9 +343,8 @@ describe('', () => {
describe('Validation', () => {
it('validates on init', async () => {
class IsCat extends Validator {
- constructor() {
- super();
- this.name = 'IsCat';
+ static get validatorName() {
+ return 'IsCat';
}
execute(value) {
@@ -376,9 +375,8 @@ describe('', () => {
it('has a special validator for all children - can be checked via this.error.FormElementsHaveNoError', async () => {
class IsCat extends Validator {
- constructor() {
- super();
- this.name = 'IsCat';
+ static get validatorName() {
+ return 'IsCat';
}
execute(value) {
@@ -405,9 +403,8 @@ describe('', () => {
it('validates on children (de)registration', async () => {
class HasEvenNumberOfChildren extends Validator {
- constructor() {
- super();
- this.name = 'HasEvenNumberOfChildren';
+ static get validatorName() {
+ return 'HasEvenNumberOfChildren';
}
execute(value) {
@@ -561,9 +558,8 @@ describe('', () => {
it('potentially shows fieldset error message on interaction change', async () => {
class Input1IsTen extends Validator {
- constructor() {
- super();
- this.name = 'Input1IsTen';
+ static get validatorName() {
+ return 'Input1IsTen';
}
execute(value) {
@@ -593,9 +589,8 @@ describe('', () => {
it('show error if tabbing "out" of last ', async () => {
class Input1IsTen extends Validator {
- constructor() {
- super();
- this.name = 'Input1IsTen';
+ static get validatorName() {
+ return 'Input1IsTen';
}
execute(value) {
@@ -916,9 +911,8 @@ describe('', () => {
it('has correct validation afterwards', async () => {
class IsCat extends Validator {
- constructor() {
- super();
- this.name = 'IsCat';
+ static get validatorName() {
+ return 'IsCat';
}
execute(value) {
@@ -927,9 +921,8 @@ describe('', () => {
}
}
class ColorContainsA extends Validator {
- constructor() {
- super();
- this.name = 'ColorContainsA';
+ static get validatorName() {
+ return 'ColorContainsA';
}
execute(value) {
diff --git a/packages/form-system/stories/17-Validation-Examples.stories.mdx b/packages/form-system/stories/17-Validation-Examples.stories.mdx
index 93e24387a..14babb3a3 100644
--- a/packages/form-system/stories/17-Validation-Examples.stories.mdx
+++ b/packages/form-system/stories/17-Validation-Examples.stories.mdx
@@ -363,9 +363,8 @@ You can even hard code localization in there if needed or you can use a localiza
{() => {
class MyValidator extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'myValidator';
+ static get validatorName() {
+ return 'myValidator';
}
execute(modelValue, param) {
return modelValue !== param;
@@ -394,7 +393,10 @@ You can even hard code localization in there if needed or you can use a localiza
class MyValidator extends Validator {
constructor(...args) {
super(...args);
- this.name = 'myValidator';
+ }
+
+ static get validatorName() {
+ return 'myValidator';
}
execute(modelValue, param) {
@@ -511,8 +513,12 @@ Oftern
class AsyncValidator extends Validator {
constructor(...args) {
super(...args);
- this.name = 'asyncValidator';
- this.async = true;
+ }
+ static get validatorName() {
+ return 'asyncValidator';
+ }
+ static get async() {
+ return true;
}
async execute() {
console.log('async pending...');
@@ -549,8 +555,12 @@ function pause(ms = 0) {
class AsyncValidator extends Validator {
constructor(...args) {
super(...args);
- this.name = 'asyncValidator';
- this.async = true;
+ }
+ static get validatorName() {
+ return 'asyncValidator';
+ }
+ static get async() {
+ return true;
}
async execute() {
console.log('async pending...');
diff --git a/packages/form-system/stories/35-System-InteractionStates.stories.mdx b/packages/form-system/stories/35-System-InteractionStates.stories.mdx
index 54793932e..9ceef3c92 100644
--- a/packages/form-system/stories/35-System-InteractionStates.stories.mdx
+++ b/packages/form-system/stories/35-System-InteractionStates.stories.mdx
@@ -105,9 +105,8 @@ In the following example we will demonstrate this with interaction states, the m
// Define a demo validator that should only be visible on an odd amount of characters
// const OddValidator = [modelValue => ({ odd: modelValue.length % 2 !== 0 })];
class OddValidator extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'OddValidator';
+ static get validatorName() {
+ return 'OddValidator';
}
// eslint-disable-next-line class-methods-use-this
execute(value) {
diff --git a/packages/form-system/stories/fieldset-examples.stories.mdx b/packages/form-system/stories/fieldset-examples.stories.mdx
index ca7ed46f9..08a62cd16 100644
--- a/packages/form-system/stories/fieldset-examples.stories.mdx
+++ b/packages/form-system/stories/fieldset-examples.stories.mdx
@@ -175,9 +175,8 @@ Try it by typing something in the input, then removing it.
{() => {
const DemoValidator = class extends Validator {
- constructor() {
- super();
- this.name = 'DemoValidator';
+ static get validatorName() {
+ return 'DemoValidator';
}
execute(value) {
if (value && value.input1) {
@@ -199,9 +198,8 @@ Try it by typing something in the input, then removing it.
```js
const DemoValidator = class extends Validator {
- constructor() {
- super();
- this.name = 'DemoValidator';
+ static get validatorName() {
+ return 'DemoValidator';
}
execute(value) {
@@ -230,9 +228,8 @@ You can have your fieldset validator take into consideration multiple fields.
{() => {
const IsCatsAndDogs = class extends Validator {
- constructor() {
- super();
- this.name = 'IsCatsAndDogs';
+ static get validatorName() {
+ return 'IsCatsAndDogs';
}
execute(value) {
return !(value.input1 === 'cats' && value.input2 === 'dogs');
@@ -262,9 +259,8 @@ You can have your fieldset validator take into consideration multiple fields.
```js
const IsCatsAndDogs = class extends Validator {
- constructor() {
- super();
- this.name = 'IsCatsAndDogs';
+ static get validatorName() {
+ return 'IsCatsAndDogs';
}
execute(value) {
@@ -308,9 +304,8 @@ You can have your fieldset validator take into accounts multiple nested fieldset
{() => {
const IsCatsDogs = class extends Validator {
- constructor() {
- super();
- this.name = 'IsCatsDogs';
+ static get validatorName() {
+ return 'IsCatsAndDogs';
}
execute(value) {
if ((value.inner1 && value.inner1.input1 === 'cats') &&
@@ -350,9 +345,8 @@ You can have your fieldset validator take into accounts multiple nested fieldset
```js
const IsCatsDogs = class extends Validator {
- constructor() {
- super();
- this.name = 'IsCatsDogs';
+ static get validatorName() {
+ return 'IsCatsDogs';
}
execute(value) {
diff --git a/packages/input-date/src/LionInputDate.js b/packages/input-date/src/LionInputDate.js
index 78f73f639..dcaab505d 100644
--- a/packages/input-date/src/LionInputDate.js
+++ b/packages/input-date/src/LionInputDate.js
@@ -1,5 +1,5 @@
-import { LocalizeMixin, formatDate, parseDate } from '@lion/localize';
import { LionInput } from '@lion/input';
+import { formatDate, LocalizeMixin, parseDate } from '@lion/localize';
import { IsDate } from '@lion/validate';
/**
@@ -41,7 +41,10 @@ export class LionInputDate extends LocalizeMixin(LionInput) {
if (!(modelValue instanceof Date)) {
return '';
}
- return modelValue.toISOString().slice(0, 10);
+ // modelValue is localized, so we take the timezone offset in milliseconds and subtract it
+ // before converting it to ISO string
+ const offset = modelValue.getTimezoneOffset() * 60000;
+ return new Date(modelValue - offset).toISOString().slice(0, 10);
}
// eslint-disable-next-line class-methods-use-this
diff --git a/packages/input-date/test/lion-input-date.test.js b/packages/input-date/test/lion-input-date.test.js
index c31f897ff..be98dcc40 100644
--- a/packages/input-date/test/lion-input-date.test.js
+++ b/packages/input-date/test/lion-input-date.test.js
@@ -141,9 +141,9 @@ describe('', () => {
it('serializes to iso format', async () => {
const el = await fixture(
html`
-
+
`,
);
- expect(el.serializedValue).to.equal('2000-12-12');
+ expect(el.serializedValue).to.equal('2000-12-15');
});
});
diff --git a/packages/input-datepicker/src/LionInputDatepicker.js b/packages/input-datepicker/src/LionInputDatepicker.js
index c2f2e965d..e5fedca78 100644
--- a/packages/input-datepicker/src/LionInputDatepicker.js
+++ b/packages/input-datepicker/src/LionInputDatepicker.js
@@ -322,14 +322,14 @@ export class LionInputDatepicker extends OverlayMixin(LionInputDate) {
// On every validator change, synchronize disabled dates: this means
// we need to extract minDate, maxDate, minMaxDate and disabledDates validators
validators.forEach(v => {
- if (v.name === 'MinDate') {
+ if (v.constructor.name === 'MinDate') {
this.__calendarMinDate = v.param;
- } else if (v.name === 'MaxDate') {
+ } else if (v.constructor.name === 'MaxDate') {
this.__calendarMaxDate = v.param;
- } else if (v.name === 'MinMaxDate') {
+ } else if (v.constructor.name === 'MinMaxDate') {
this.__calendarMinDate = v.param.min;
this.__calendarMaxDate = v.param.max;
- } else if (v.name === 'IsDateDisabled') {
+ } else if (v.constructor.name === 'IsDateDisabled') {
this.__calendarDisableDates = v.param;
}
});
diff --git a/packages/input-email/stories/index.stories.mdx b/packages/input-email/stories/index.stories.mdx
index c135649e6..68386148e 100644
--- a/packages/input-email/stories/index.stories.mdx
+++ b/packages/input-email/stories/index.stories.mdx
@@ -69,9 +69,8 @@ loadDefaultFeedbackMessages();
{() => {
class GmailOnly extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'GmailOnly';
+ static get validatorName() {
+ return 'GmailOnly';
}
execute(value) {
let hasError = false;
@@ -98,9 +97,8 @@ loadDefaultFeedbackMessages();
import { Validator } from '@lion/validate';
class GmailOnly extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'GmailOnly';
+ static get validatorName() {
+ return 'GmailOnly';
}
execute(value) {
diff --git a/packages/input-iban/src/validators.js b/packages/input-iban/src/validators.js
index b9af119c4..aaf94149c 100644
--- a/packages/input-iban/src/validators.js
+++ b/packages/input-iban/src/validators.js
@@ -1,8 +1,8 @@
/* eslint-disable max-classes-per-file */
-import { isValidIBAN } from 'ibantools';
-import { Validator } from '@lion/validate';
import { localize } from '@lion/localize';
+import { Validator } from '@lion/validate';
+import { isValidIBAN } from 'ibantools';
let loaded = false;
const loadTranslations = async () => {
@@ -19,9 +19,8 @@ const loadTranslations = async () => {
};
export class IsIBAN extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'IsIBAN';
+ static get validatorName() {
+ return 'IsIBAN';
}
// eslint-disable-next-line class-methods-use-this
@@ -36,9 +35,8 @@ export class IsIBAN extends Validator {
}
export class IsCountryIBAN extends IsIBAN {
- constructor(...args) {
- super(...args);
- this.name = 'IsCountryIBAN';
+ static get validatorName() {
+ return 'IsCountryIBAN';
}
execute(value) {
diff --git a/packages/radio-group/stories/index.stories.mdx b/packages/radio-group/stories/index.stories.mdx
index 5bc947955..332f87740 100644
--- a/packages/radio-group/stories/index.stories.mdx
+++ b/packages/radio-group/stories/index.stories.mdx
@@ -192,9 +192,8 @@ You can also create a validator that validates whether a certain option is check
{() => {
class IsBrontosaurus extends Validator {
- constructor() {
- super();
- this.name = 'IsBrontosaurus';
+ static get validatorName() {
+ return 'IsBrontosaurus';
}
execute(value) {
return value === 'brontosaurus';
@@ -227,9 +226,8 @@ You can also create a validator that validates whether a certain option is check
import { loadDefaultFeedbackMessages, Required, Validator } from 'lion/validate';
class IsBrontosaurus extends Validator {
- constructor() {
- super();
- this.name = 'IsBrontosaurus';
+ static get validatorName() {
+ return 'IsBrontosaurus';
}
execute(value) {
return value === 'brontosaurus';
diff --git a/packages/switch/stories/index.stories.mdx b/packages/switch/stories/index.stories.mdx
index 47c76b267..377549155 100644
--- a/packages/switch/stories/index.stories.mdx
+++ b/packages/switch/stories/index.stories.mdx
@@ -1,6 +1,7 @@
import { Story, Meta, html } from '@open-wc/demoing-storybook';
import { Validator } from '@lion/validate';
+import { LionSwitch } from '../src/LionSwitch';
import '../lion-switch.js';
@@ -64,9 +65,8 @@ Simple example that illustrates where validation feedback will be displayed.
{() => {
const IsTrue = class extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'IsTrue';
+ static get validatorName() {
+ return 'IsTrue';
}
execute(value) {
return !value.checked;
@@ -75,24 +75,30 @@ Simple example that illustrates where validation feedback will be displayed.
return "You won't get the latest news!";
}
};
+ class CustomSwitch extends LionSwitch {
+ static get validationTypes() {
+ return [...super.validationTypes, 'info'];
+ }
+ }
+ customElements.define('custom-switch', CustomSwitch);
return html`
-
+ .validators="${[new IsTrue(null, { type: 'info' })]}"
+ >
`;
}}
```js
import { Validator } from '@lion/validate';
+import { LionSwitch } from '@lion/switch/src/LionSwitch';
const IsTrue = class extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'IsTrue';
+ static get validatorName() {
+ return 'IsTrue';
}
execute(value) {
return !value.checked;
@@ -101,13 +107,20 @@ const IsTrue = class extends Validator {
return "You won't get the latest news!";
}
};
+
+class CustomSwitch extends LionSwitch {
+ static get validationTypes() {
+ return [...super.validationTypes, 'info'];
+ }
+}
+customElements.define('custom-switch', CustomSwitch);
```
```html
-
+>
```
diff --git a/packages/validate/README.md b/packages/validate/README.md
index 09c14c464..d0e7523c8 100644
--- a/packages/validate/README.md
+++ b/packages/validate/README.md
@@ -42,9 +42,8 @@ import { Required, IsString, MaxLength, DefaultSuccess, Validator } from '@lion/
const isInitialsRegex = /^([A-Z]\.)+$/;
class IsInitialsExample extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'IsExampleInitials';
+ static get validatorName() {
+ return 'IsExampleInitials';
}
execute(value) {
diff --git a/packages/validate/src/ValidateMixin.js b/packages/validate/src/ValidateMixin.js
index e13fa7f4d..e1f8f2425 100644
--- a/packages/validate/src/ValidateMixin.js
+++ b/packages/validate/src/ValidateMixin.js
@@ -323,8 +323,12 @@ export const ValidateMixin = dedupeMixin(
const /** @type {Validator[]} */ filteredValidators = this._allValidators.filter(
v => !(v instanceof ResultValidator) && !(v instanceof Required),
);
- const /** @type {Validator[]} */ syncValidators = filteredValidators.filter(v => !v.async);
- const /** @type {Validator[]} */ asyncValidators = filteredValidators.filter(v => v.async);
+ const /** @type {Validator[]} */ syncValidators = filteredValidators.filter(
+ v => !v.constructor.async,
+ );
+ const /** @type {Validator[]} */ asyncValidators = filteredValidators.filter(
+ v => v.constructor.async,
+ );
/**
* 2. Synchronous validators
@@ -378,7 +382,7 @@ export const ValidateMixin = dedupeMixin(
__executeResultValidators(regularValidationResult) {
/** @type {ResultValidator[]} */
const resultValidators = this._allValidators.filter(
- v => !v.async && v instanceof ResultValidator,
+ v => !v.constructor.async && v instanceof ResultValidator,
);
return resultValidators.filter(v =>
@@ -415,7 +419,7 @@ export const ValidateMixin = dedupeMixin(
if (!validationStates[v.type]) {
validationStates[v.type] = {};
}
- validationStates[v.type][v.name] = true;
+ validationStates[v.type][v.constructor.name] = true;
});
this.validationStates = validationStates;
this.hasFeedbackFor = [...new Set(this.__validationResult.map(v => v.type))];
@@ -457,7 +461,7 @@ export const ValidateMixin = dedupeMixin(
}
if (this.constructor.validationTypes.indexOf(v.type) === -1) {
// throws in constructor are not visible to end user so we do both
- const errorMessage = `This component does not support the validator type "${v.type}" used in "${v.name}". You may change your validators type or add it to the components "static get validationTypes() {}".`;
+ const errorMessage = `This component does not support the validator type "${v.type}" used in "${v.constructor.validatorName}". You may change your validators type or add it to the components "static get validationTypes() {}".`;
// eslint-disable-next-line no-console
console.error(errorMessage, this);
throw new Error(errorMessage);
diff --git a/packages/validate/src/Validator.js b/packages/validate/src/Validator.js
index 82b78118c..904dcacdb 100644
--- a/packages/validate/src/Validator.js
+++ b/packages/validate/src/Validator.js
@@ -4,13 +4,19 @@ export class Validator {
constructor(param, config) {
fakeExtendsEventTarget(this);
- this.name = '';
- this.async = false;
this.__param = param;
this.__config = config || {};
this.type = (config && config.type) || 'error'; // Default type supported by ValidateMixin
}
+ static get validatorName() {
+ return '';
+ }
+
+ static get async() {
+ return false;
+ }
+
/**
* @desc The function that returns a Boolean
* @param {string|Date|Number|object} modelValue
@@ -18,8 +24,10 @@ export class Validator {
* @returns {Boolean|Promise}
*/
execute(/* modelValue, param */) {
- if (!this.name) {
- throw new Error('You must provide a name like "this.name = \'IsCat\'" for your Validator');
+ if (!this.validatorName) {
+ throw new Error(
+ 'A validator needs to have a name! Please set it via "static get validatorName() { return \'IsCat\'; }"',
+ );
}
}
@@ -52,7 +60,7 @@ export class Validator {
*/
async _getMessage(data) {
const composedData = {
- name: this.name,
+ name: this.constructor.validatorName,
type: this.type,
params: this.param,
config: this.config,
diff --git a/packages/validate/src/validators/DateValidators.js b/packages/validate/src/validators/DateValidators.js
index f083d6582..16e928ab6 100644
--- a/packages/validate/src/validators/DateValidators.js
+++ b/packages/validate/src/validators/DateValidators.js
@@ -9,9 +9,8 @@ function isDate(value) {
}
export class IsDate extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'IsDate';
+ static get validatorName() {
+ return 'IsDate';
}
// eslint-disable-next-line class-methods-use-this
@@ -25,9 +24,8 @@ export class IsDate extends Validator {
}
export class MinDate extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'MinDate';
+ static get validatorName() {
+ return 'MinDate';
}
execute(value, min = this.param) {
@@ -40,9 +38,8 @@ export class MinDate extends Validator {
}
export class MaxDate extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'MaxDate';
+ static get validatorName() {
+ return 'MaxDate';
}
execute(value, max = this.param) {
@@ -55,9 +52,8 @@ export class MaxDate extends Validator {
}
export class MinMaxDate extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'MinMaxDate';
+ static get validatorName() {
+ return 'MinMaxDate';
}
execute(value, { min = 0, max = 0 } = this.param) {
@@ -70,9 +66,8 @@ export class MinMaxDate extends Validator {
}
export class IsDateDisabled extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'IsDateDisabled';
+ static get validatorName() {
+ return 'IsDateDisabled';
}
execute(value, isDisabledFn = this.param) {
diff --git a/packages/validate/src/validators/NumberValidators.js b/packages/validate/src/validators/NumberValidators.js
index a2618ba6b..520ed398f 100644
--- a/packages/validate/src/validators/NumberValidators.js
+++ b/packages/validate/src/validators/NumberValidators.js
@@ -11,9 +11,8 @@ const isNumber = value =>
value === value && typeof value === 'number';
export class IsNumber extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'IsNumber';
+ static get validatorName() {
+ return 'IsNumber';
}
// eslint-disable-next-line class-methods-use-this
@@ -27,9 +26,8 @@ export class IsNumber extends Validator {
}
export class MinNumber extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'MinNumber';
+ static get validatorName() {
+ return 'MinNumber';
}
execute(value, min = this.param) {
@@ -42,9 +40,8 @@ export class MinNumber extends Validator {
}
export class MaxNumber extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'MaxNumber';
+ static get validatorName() {
+ return 'MaxNumber';
}
execute(value, max = this.param) {
@@ -57,9 +54,8 @@ export class MaxNumber extends Validator {
}
export class MinMaxNumber extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'MinMaxNumber';
+ static get validatorName() {
+ return 'MinMaxNumber';
}
execute(value, { min = 0, max = 0 } = this.param) {
diff --git a/packages/validate/src/validators/Required.js b/packages/validate/src/validators/Required.js
index 13ba04ca4..6ae652766 100644
--- a/packages/validate/src/validators/Required.js
+++ b/packages/validate/src/validators/Required.js
@@ -1,9 +1,8 @@
import { Validator } from '../Validator.js';
export class Required extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'Required';
+ static get validatorName() {
+ return 'Required';
}
/**
diff --git a/packages/validate/src/validators/StringValidators.js b/packages/validate/src/validators/StringValidators.js
index 11d56a13a..9f0576c16 100644
--- a/packages/validate/src/validators/StringValidators.js
+++ b/packages/validate/src/validators/StringValidators.js
@@ -4,9 +4,8 @@ import { Validator } from '../Validator.js';
const isString = value => typeof value === 'string';
export class IsString extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'IsString';
+ static get validatorName() {
+ return 'IsString';
}
// eslint-disable-next-line class-methods-use-this
@@ -20,9 +19,8 @@ export class IsString extends Validator {
}
export class EqualsLength extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'EqualsLength';
+ static get validatorName() {
+ return 'EqualsLength';
}
execute(value, length = this.param) {
@@ -35,9 +33,8 @@ export class EqualsLength extends Validator {
}
export class MinLength extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'MinLength';
+ static get validatorName() {
+ return 'MinLength';
}
execute(value, min = this.param) {
@@ -50,9 +47,8 @@ export class MinLength extends Validator {
}
export class MaxLength extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'MaxLength';
+ static get validatorName() {
+ return 'MaxLength';
}
execute(value, max = this.param) {
@@ -65,9 +61,8 @@ export class MaxLength extends Validator {
}
export class MinMaxLength extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'MinMaxLength';
+ static get validatorName() {
+ return 'MinMaxLength';
}
execute(value, { min = 0, max = 0 } = this.param) {
@@ -81,9 +76,8 @@ export class MinMaxLength extends Validator {
const isEmailRegex = /^(([^<>()[\]\\.,;:\s@"]+(\.[^<>()[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
export class IsEmail extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'IsEmail';
+ static get validatorName() {
+ return 'IsEmail';
}
// eslint-disable-next-line class-methods-use-this
diff --git a/packages/validate/stories/Overview.stories.mdx b/packages/validate/stories/Overview.stories.mdx
index 06a88a473..92589370b 100644
--- a/packages/validate/stories/Overview.stories.mdx
+++ b/packages/validate/stories/Overview.stories.mdx
@@ -46,11 +46,6 @@ All validators extend from the default `Validator` class. Below example is an ex
```js
class MyValidator extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'MyValidator';
- }
-
execute(modelValue, param) {
const hasFeedback = false;
if (modelValue === param) {
@@ -59,6 +54,10 @@ class MyValidator extends Validator {
return hasFeedback;
}
+ static get validatorName() {
+ return 'Required';
+ }
+
static getMessage({ fieldName }) {
return `Please fill in ${fieldName}`;
}
@@ -87,7 +86,7 @@ You can implement your own custom message for a default validator. Pass a getMes
```js
function getCustomMessage(data) {
- return `${data.name} is a required field`;
+ return `${data.validatorName} is a required field`;
}
```
@@ -113,12 +112,6 @@ You can make your async validators as follows:
```js
class AsyncValidator extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'AsyncValidator';
- this.async = true;
- }
-
async execute() {
console.log('async pending...');
await pause(2000);
@@ -126,6 +119,12 @@ class AsyncValidator extends Validator {
return true;
}
+ static get validatorName() {
+ return 'AsyncValidator';
+ }
+
+ static get async() { return true; }
+
static getMessage({ modelValue }) {
return `Validated for modelValue: ${modelValue}`;
}
diff --git a/packages/validate/test-helpers/ExampleValidators.js b/packages/validate/test-helpers/ExampleValidators.js
index 014d0d08f..cc54bc5ab 100644
--- a/packages/validate/test-helpers/ExampleValidators.js
+++ b/packages/validate/test-helpers/ExampleValidators.js
@@ -2,9 +2,8 @@
import { Validator } from '../src/Validator.js';
export class AlwaysInvalid extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'AlwaysInvalid';
+ static get validatorName() {
+ return 'AlwaysInvalid';
}
execute() {
@@ -14,9 +13,8 @@ export class AlwaysInvalid extends Validator {
}
export class AlwaysValid extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'AlwaysValid';
+ static get validatorName() {
+ return 'AlwaysValid';
}
execute() {
@@ -26,9 +24,8 @@ export class AlwaysValid extends Validator {
}
export class AsyncAlwaysValid extends AlwaysValid {
- constructor(...args) {
- super(...args);
- this.async = true;
+ static get async() {
+ return true;
}
execute() {
@@ -37,9 +34,8 @@ export class AsyncAlwaysValid extends AlwaysValid {
}
export class AsyncAlwaysInvalid extends AlwaysValid {
- constructor(...args) {
- super(...args);
- this.async = true;
+ static get async() {
+ return true;
}
async execute() {
diff --git a/packages/validate/test-suites/ValidateMixin.suite.js b/packages/validate/test-suites/ValidateMixin.suite.js
index 8b965b548..3ee9baa92 100644
--- a/packages/validate/test-suites/ValidateMixin.suite.js
+++ b/packages/validate/test-suites/ValidateMixin.suite.js
@@ -1,22 +1,21 @@
-import { expect, fixture, html, unsafeStatic, defineCE, aTimeout } from '@open-wc/testing';
-import sinon from 'sinon';
import { LitElement } from '@lion/core';
+import { aTimeout, defineCE, expect, fixture, html, unsafeStatic } from '@open-wc/testing';
+import sinon from 'sinon';
import {
- AlwaysValid,
- AlwaysInvalid,
- AsyncAlwaysValid,
- AsyncAlwaysInvalid,
-} from '../test-helpers.js';
-
-import {
- ValidateMixin,
- Unparseable,
- Validator,
- ResultValidator,
- Required,
- MinLength,
MaxLength,
+ MinLength,
+ Required,
+ ResultValidator,
+ Unparseable,
+ ValidateMixin,
+ Validator,
} from '../index.js';
+import {
+ AlwaysInvalid,
+ AlwaysValid,
+ AsyncAlwaysInvalid,
+ AsyncAlwaysValid,
+} from '../test-helpers.js';
export function runValidateMixinSuite(customConfig) {
const cfg = {
@@ -104,9 +103,12 @@ export function runValidateMixinSuite(customConfig) {
class MajorValidator extends Validator {
constructor() {
super();
- this.name = 'MajorValidator';
this.type = 'major error';
}
+
+ static get validatorName() {
+ return 'MajorValidator';
+ }
}
const el = await fixture(html`<${tag}>${tag}>`);
expect(() => {
@@ -218,9 +220,8 @@ export function runValidateMixinSuite(customConfig) {
it('finally checks for ResultValidators: creates TotalValidationResult', async () => {
class MyResult extends ResultValidator {
- constructor(...args) {
- super(...args);
- this.name = 'ResultValidator';
+ static get validatorName() {
+ return 'ResultValidator';
}
}
@@ -285,21 +286,27 @@ export function runValidateMixinSuite(customConfig) {
class IsCat extends Validator {
constructor(...args) {
super(...args);
- this.name = 'isCat';
this.execute = (modelValue, param) => {
const validateString = param && param.number ? `cat${param.number}` : 'cat';
const showError = modelValue !== validateString;
return showError;
};
}
+
+ static get validatorName() {
+ return 'isCat';
+ }
}
class OtherValidator extends Validator {
constructor(...args) {
super(...args);
- this.name = 'otherValidator';
this.execute = () => true;
}
+
+ static get validatorName() {
+ return 'otherValidator';
+ }
}
it('Validators will be called with ".modelValue" as first argument', async () => {
@@ -357,11 +364,11 @@ export function runValidateMixinSuite(customConfig) {
`);
el.modelValue = 'cat';
- expect(el.validationStates.error.isCat).to.be.undefined;
+ expect(el.validationStates.error.IsCat).to.be.undefined;
el.modelValue = 'dog';
- expect(el.validationStates.error.isCat).to.be.true;
+ expect(el.validationStates.error.IsCat).to.be.true;
el.modelValue = '';
- expect(el.validationStates.error.isCat).to.be.undefined;
+ expect(el.validationStates.error.IsCat).to.be.undefined;
});
it('Validators get retriggered on parameter change', async () => {
@@ -391,10 +398,12 @@ export function runValidateMixinSuite(customConfig) {
});
class IsAsyncCat extends Validator {
- constructor(param, config) {
- super(param, config);
- this.name = 'delayed-cat';
- this.async = true;
+ static get validatorName() {
+ return 'delayed-cat';
+ }
+
+ static get async() {
+ return true;
}
/**
@@ -769,20 +778,26 @@ export function runValidateMixinSuite(customConfig) {
class ContainsLowercaseA extends Validator {
constructor(...args) {
super(...args);
- this.name = 'ContainsLowercaseA';
this.execute = modelValue => !modelValue.includes('a');
}
+
+ static get validatorName() {
+ return 'ContainsLowercaseA';
+ }
}
class ContainsLowercaseB extends Validator {
constructor(...args) {
super(...args);
- this.name = 'containsLowercaseB';
this.execute = modelValue => !modelValue.includes('b');
}
+
+ static get validatorName() {
+ return 'containsLowercaseB';
+ }
}
- it('stores validity of individual Validators in ".validationStates.error[validator.name]"', async () => {
+ it('stores validity of individual Validators in ".validationStates.error[validator.validatorName]"', async () => {
const el = await fixture(html`
<${tag}
.modelValue=${'a'}
diff --git a/packages/validate/test-suites/ValidateMixinFeedbackPart.suite.js b/packages/validate/test-suites/ValidateMixinFeedbackPart.suite.js
index 85150094c..fc845fe8e 100644
--- a/packages/validate/test-suites/ValidateMixinFeedbackPart.suite.js
+++ b/packages/validate/test-suites/ValidateMixinFeedbackPart.suite.js
@@ -41,9 +41,8 @@ export function runValidateMixinFeedbackPart() {
tag = unsafeStatic(tagString);
ContainsLowercaseA = class extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'ContainsLowercaseA';
+ static get validatorName() {
+ return 'ContainsLowercaseA';
}
execute(modelValue) {
@@ -53,9 +52,8 @@ export function runValidateMixinFeedbackPart() {
};
class ContainsCat extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'ContainsCat';
+ static get validatorName() {
+ return 'ContainsCat';
}
execute(modelValue) {
@@ -244,7 +242,7 @@ export function runValidateMixinFeedbackPart() {
render() {
return html`
- Custom for ${this.feedbackData[0].validator.name}
+ Custom for ${this.feedbackData[0].validator.constructor.name}
`;
}
},
diff --git a/packages/validate/test/DateValidators.test.js b/packages/validate/test/DateValidators.test.js
index ea392c247..4415b6023 100644
--- a/packages/validate/test/DateValidators.test.js
+++ b/packages/validate/test/DateValidators.test.js
@@ -13,7 +13,7 @@ describe('Date Validation', () => {
it('provides new isDate() to allow only dates', () => {
let isEnabled;
const validator = new IsDate();
- expect(validator.name).to.equal('IsDate');
+ expect(validator.constructor.name).to.equal('IsDate');
isEnabled = validator.execute(new Date());
expect(isEnabled).to.be.false;
@@ -28,7 +28,7 @@ describe('Date Validation', () => {
it('provides new minDate(x) to allow only dates after min', () => {
let isEnabled;
const validator = new MinDate(new Date('2018/02/02'));
- expect(validator.name).to.equal('MinDate');
+ expect(validator.constructor.name).to.equal('MinDate');
isEnabled = validator.execute(new Date('2018-02-03'));
expect(isEnabled).to.be.false;
@@ -46,7 +46,7 @@ describe('Date Validation', () => {
it('provides maxDate() to allow only dates before max', () => {
let isEnabled;
const validator = new MaxDate(new Date('2018/02/02'));
- expect(validator.name).to.equal('MaxDate');
+ expect(validator.constructor.name).to.equal('MaxDate');
isEnabled = validator.execute(new Date('2018-02-01'));
expect(isEnabled).to.be.false;
@@ -67,7 +67,7 @@ describe('Date Validation', () => {
min: new Date('2018/02/02'),
max: new Date('2018/02/04'),
});
- expect(validator.name).to.equal('MinMaxDate');
+ expect(validator.constructor.name).to.equal('MinMaxDate');
isEnabled = validator.execute(new Date('2018/02/03'));
expect(isEnabled).to.be.false;
@@ -88,7 +88,7 @@ describe('Date Validation', () => {
it('provides new IsDateDisabled() to disable dates matching specified condition', () => {
let isDisabled;
const validator = new IsDateDisabled(d => d.getDate() === 3);
- expect(validator.name).to.equal('IsDateDisabled');
+ expect(validator.constructor.name).to.equal('IsDateDisabled');
isDisabled = validator.execute(new Date('2018/02/04'));
expect(isDisabled).to.be.false;
diff --git a/packages/validate/test/NumberValidators.test.js b/packages/validate/test/NumberValidators.test.js
index 43aadbaea..d4a9ed991 100644
--- a/packages/validate/test/NumberValidators.test.js
+++ b/packages/validate/test/NumberValidators.test.js
@@ -11,7 +11,7 @@ describe('Number Validation', () => {
it('provides new IsNumber() to allow only numbers', () => {
let isEnabled;
const validator = new IsNumber();
- expect(validator.name).to.equal('IsNumber');
+ expect(validator.constructor.name).to.equal('IsNumber');
isEnabled = validator.execute(4);
expect(isEnabled).to.be.false;
@@ -26,7 +26,7 @@ describe('Number Validation', () => {
it('provides new MinNumber(x) to allow only numbers longer then min', () => {
let isEnabled;
const validator = new MinNumber(3);
- expect(validator.name).to.equal('MinNumber');
+ expect(validator.constructor.name).to.equal('MinNumber');
isEnabled = validator.execute(3);
expect(isEnabled).to.be.false;
@@ -38,7 +38,7 @@ describe('Number Validation', () => {
it('provides new MaxNumber(x) to allow only number shorter then max', () => {
let isEnabled;
const validator = new MaxNumber(3);
- expect(validator.name).to.equal('MaxNumber');
+ expect(validator.constructor.name).to.equal('MaxNumber');
isEnabled = validator.execute(3);
expect(isEnabled).to.be.false;
@@ -50,7 +50,7 @@ describe('Number Validation', () => {
it('provides new MinMaxNumber({ min: x, max: y}) to allow only numbers between min and max', () => {
let isEnabled;
const validator = new MinMaxNumber({ min: 2, max: 4 });
- expect(validator.name).to.equal('MinMaxNumber');
+ expect(validator.constructor.name).to.equal('MinMaxNumber');
isEnabled = validator.execute(2);
expect(isEnabled).to.be.false;
diff --git a/packages/validate/test/StringValidators.test.js b/packages/validate/test/StringValidators.test.js
index b29d7aaaf..df98ff375 100644
--- a/packages/validate/test/StringValidators.test.js
+++ b/packages/validate/test/StringValidators.test.js
@@ -13,7 +13,7 @@ describe('String Validation', () => {
it('provides new IsString() to allow only strings', () => {
let isEnabled;
const validator = new IsString();
- expect(validator.name).to.equal('IsString');
+ expect(validator.constructor.name).to.equal('IsString');
isEnabled = validator.execute('foo');
expect(isEnabled).to.be.false;
@@ -28,7 +28,7 @@ describe('String Validation', () => {
it('provides new EqualsLength(x) to allow only a specific string length', () => {
let isEnabled;
const validator = new EqualsLength(3);
- expect(validator.name).to.equal('EqualsLength');
+ expect(validator.constructor.name).to.equal('EqualsLength');
isEnabled = validator.execute('foo');
expect(isEnabled).to.be.false;
@@ -43,7 +43,7 @@ describe('String Validation', () => {
it('provides new MinLength(x) to allow only strings longer then min', () => {
let isEnabled;
const validator = new MinLength(3);
- expect(validator.name).to.equal('MinLength');
+ expect(validator.constructor.name).to.equal('MinLength');
isEnabled = validator.execute('foo');
expect(isEnabled).to.be.false;
@@ -55,7 +55,7 @@ describe('String Validation', () => {
it('provides new MaxLength(x) to allow only strings shorter then max', () => {
let isEnabled;
const validator = new MaxLength(3);
- expect(validator.name).to.equal('MaxLength');
+ expect(validator.constructor.name).to.equal('MaxLength');
isEnabled = validator.execute('foo');
expect(isEnabled).to.be.false;
@@ -67,7 +67,7 @@ describe('String Validation', () => {
it('provides new MinMaxValidator({ min: x, max: y}) to allow only strings between min and max', () => {
let isEnabled;
const validator = new MinMaxLength({ min: 2, max: 4 });
- expect(validator.name).to.equal('MinMaxLength');
+ expect(validator.constructor.name).to.equal('MinMaxLength');
isEnabled = validator.execute('foo');
expect(isEnabled).to.be.false;
@@ -82,7 +82,7 @@ describe('String Validation', () => {
it('provides new IsEmail() to allow only valid email formats', () => {
let isEnabled;
const validator = new IsEmail();
- expect(validator.name).to.equal('IsEmail');
+ expect(validator.constructor.name).to.equal('IsEmail');
isEnabled = validator.execute('foo@bar.com');
expect(isEnabled).to.be.false;
diff --git a/packages/validate/test/Validator.test.js b/packages/validate/test/Validator.test.js
index 166b3f428..06184ba1c 100644
--- a/packages/validate/test/Validator.test.js
+++ b/packages/validate/test/Validator.test.js
@@ -32,14 +32,15 @@ describe('Validator', () => {
class MyValidator extends Validator {}
expect(() => {
new MyValidator().execute();
- }).to.throw('You must provide a name like "this.name = \'IsCat\'" for your Validator');
+ }).to.throw(
+ 'A validator needs to have a name! Please set it via "static get validatorName() { return \'IsCat\'; }"',
+ );
});
it('throws when executing a Validator that has a getMessage config property with a value not of type function', async () => {
class MyValidator extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'MyValidator';
+ static get validatorName() {
+ return 'MyValidator';
}
}
@@ -62,9 +63,8 @@ describe('Validator', () => {
it('has access to name, type, params, config in getMessage provided by config', () => {
const configSpy = sinon.spy();
class MyValidator extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'MyValidator';
+ static get validatorName() {
+ return 'MyValidator';
}
}
const vali = new MyValidator('myParam', { my: 'config', getMessage: configSpy });
@@ -81,9 +81,8 @@ describe('Validator', () => {
it('has access to name, type, params, config in static get getMessage', () => {
let staticArgs;
class MyValidator extends Validator {
- constructor(...args) {
- super(...args);
- this.name = 'MyValidator';
+ static get validatorName() {
+ return 'MyValidator';
}
static getMessage(...args) {