What's new in v3.2.0
PlumeJS internally makes use of CSSStyleSheet constructor to enable styling of webcomponents. As this is relatively newer technology (which supports only in Chrome, Edge & Mozilla), this update provides better fallback mechanism if a browser doesn't support CSSStyleSheet constructor. Along with this, the new update also brings improvements to useFormFields hook which was introduced in v3.0.0. The feature upgrade for this hook enables developers to pass a single or multiple validators for a form field (Just like validations in reactive forms in angular for instance). It also brings a new Form interface which provides apis like:
form.valuereturns an object of form field name and value as key-value pair.form.validto check the validity of the form.form.errorsis aMapcontaining field name as key and error object as value. Developer can query this map for a field to extract errors easily. This also used to display summary of error messages.form.get(<-your-field-name->)to read a form field's value or errors or validators.form.reset()to reset the form to initial state.
One advantage of this newer Form interface is form.errors which gives developers the error summary of all form fields.
form: Form;
...
[this.form, this.createChangeHandler] = useFormFields({...});Not all is good. The newer inplementation brings slight inconvinience.
Before the update, the sample form looks like this:
import { Component, html, useFormFields } from '@plumejs/core';
interface IFormFields {
email: string;
checkme: boolean;
option: string;
gender: string
}
@Component(...)
class SampleForm {
sampleformFields: IFormFields;
createChangeHandler: any;
constructor() {
[ this.sampleformFields, this.createChangeHandler, this.resetFormFields ] = useFormFields<IFormFields>({
email: "",
checkme: false,
option: '',
gender: "",
});
this.submitForm = this.submitForm.bind(this);
}
submitForm(e: Event) {
e.preventDefault();
console.log(this.sampleformFields);
}
render() {
return html`
<form onsubmit=${this.submitForm}>
<div>
<label>textbox</label>
<input onchange=${this.createChangeHandler("email")}/>
</div>
<div>
<b>radio</b>
<input
type="radio"
id="gender_male"
name="gender"
value="male"
onchange=${this.createChangeHandler("gender")}
/>
<label for="gender_male">Male</label>
<input
type="radio"
id="gender_female"
name="gender"
value="female"
onchange=${this.createChangeHandler("gender")}
/>
<label for="gender_female">Female</label>
<div>
<div>
<label>checkbox</label>
<input
type="checkbox"
name="gender"
value="male"
onchange=${this.createChangeHandler("checkme")}
/>
<div>
<div>
<label>single select</label>
<select value=${this.sampleformFields.option} onchange=${this.createChangeHandler("option")}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<div>
<button type="submit" class="button is-info">Submit</button>
</form>
`
}
}From the new version, the implementation looks like this:
import { Component, html, useFormFields, Form } from '@plumejs/core';
interface IFormFields {
email: string;
checkme: boolean;
option: string;
options: string[]
gender: string
}
@Component(...)
class SampleForm {
sampleform: Form<IFormFields>;
createChangeHandler: any;
constructor() {
[this.sampleform, this.createChangeHandler] = useFormFields<IFormFields>({
email: "",
checkme: false,
option: '',
options: [['1', '2']] //this syntax is must for multi-select dropdown options
gender: "",
});
this.submitForm = this.submitForm.bind(this);
}
submitForm(e: Event) {
e.preventDefault();
console.log(this.sampleform.value);
}
reset() {
this.sampleForm.reset();
}
render() {
return html`
<form onsubmit=${this.submitForm}>
<div>
<label>textbox</label>
<input onchange=${this.createChangeHandler("email")}/>
</div>
<div>
<b>radio</b>
<input
type="radio"
id="gender_male"
name="gender"
value="male"
onchange=${this.createChangeHandler("gender")}
/>
<label for="gender_male">Male</label>
<input
type="radio"
id="gender_female"
name="gender"
value="female"
onchange=${this.createChangeHandler("gender")}
/>
<label for="gender_female">Female</label>
<div>
<div>
<label>checkbox</label>
<input
type="checkbox"
name="gender"
value="male"
onchange=${this.createChangeHandler("checkme")}
/>
<div>
<div>
<label>single select</label>
<select value=${this.sampleform.get('option').value} onchange=${this.createChangeHandler("option")}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<div>
<div>
<label>multi select</label>
<select multiple value=${this.sampleform.get('options').value} onchange=${this.createChangeHandler("options")}>
<option value="1">1</option>
<option value="2">2</option>
<option value="3">3</option>
<option value="4">4</option>
</select>
<div>
<button type='button' onclick=${() => this.reset()}>Reset</button>
<button type="submit" class="button is-info">Submit</button>
</form>
`
}
}Previously, useFormFields also returns resetFormFields function to reset the form. But with the introduction of Form interface, this function becomes redundant and will be removed in future versions.
The new update also brings one notable feature called standalone components. Standalone components doesn't rely on any type of global styles apart from inheriting fonts. Such components design is purely dictated by their own styles. This doesn't mean like developers have to write components in different manner 😉.
@Component({
selector: 'my-app',
styles: '',
standalone: true
})
class YourComponent {...}That's it. a new standalone property in component decorator options make your component standalone.
Translations which are built-in core module is removed. Instead devs are encouraged to check docs on how to setup translations manually. The intention behind this change is to make PlumeJS almost dependency free (few polyfills are needed here and then for unsupported features). Hope you welcome this change.