Skip to content Common
Slotted label Slotted label Slotted label
Slotted help text Complex help text
Web components
...
Common concepts
Common model
concepts
We can use the flags model
to set the value from the parent component. Otherwise, the component will manage its state (model value) internally:
model
can be manipulated using javaScript. Some helpers are provided in the @zurich/dev-utils
package to ease this process:
html
<!DOCTYPE html>
<html>
<body>
<z-text-input id="my-text-input" label="Text input"/>
<script type="module">
const textInputEl = document.getElementById('my-text-input')
if (textInputEl) textInputEl.value === true;
</script>
</body>
</html>
html
<!DOCTYPE html>
<html>
<body>
<z-text-input id="my-text-input" label="Text input"/>
<output id="my-text-input-output"></output>
<script type="module">
const textInputEl = document.getElementById('my-text-input')
const textInputOutput = document.getElementById('my-text-input-output');
let textInputValue = false;
if (textInputEl) onSwitchValueChange(textInputEl)
textInputEl?.addEventListener('change', ({ detail }) => {
onSwitchValueChange(detail)
})
function onSwitchValueChange (value) {
textInputValue = value;
toggleAttribute(textInputEl, 'model', value);
textInputOutput.innerText = value;
}
function toggleAttribute (element, attrName, value) {
if (value === undefined) element.setAttribute(attrName, value)
else element.removeAttribute(attrName)
}
</script>
</body>
</html>
html
<!DOCTYPE html>
<html>
<body>
<z-text-input id="my-text-input" label="Text input"/>
<output id="my-text-input-output"></output>
<script type="module">
import { bindInputChange } from '@zurich/dev-utils/helpers';
const textInputEl = document.getElementById('my-text-input')
const textInputOutput = document.getElementById('my-text-input-output');
let textInputValue = false;
if (textInputEl) textInputOutput.innerText = value;
bindInputChange(textInputEl, (value) => {
textInputValue = value;
textInputOutput.innerText = value;
})
</script>
</body>
</html>
label
The label
can be set as a parameter:
Or using the label
slot
This allow us to build up more complex things like a hint in the input label:
I agree the
disabled
The disabled
flag avoid any UI interaction with the input as it would be done with a regular HTMLInputElement
, making the element not mutable, focusable, or even submitted with the form.
name
Defines the name use un the form for that field. Must be unique in the form. Follows the HTML standard.
required
As with the regular HTMLInputElement
API, indicates that the user must specify a value for the input before the owning form can be submitted.
help-text
Not every input has the help-text
option.
The help-text
can be set as a parameter or using the help-text
slot:
This allow us to build up more complex things in the help text:
In boolean inputs this text will only be shown if a label
is provided:
reset()
method
A method of the input web components to reset the value.
Boolean inputs
They are inputs that are always going to manage a boolean
as the model value.
The available Web boolean inputs are:
model
and checked
We can use the flags value
or checked
to set the value:
Boolean inputs validation
The validation of the inputs can be controlled using the invalid
attribute:
The required
property will make the boolean input invalid if this is not set to true
. The invalid state will disappear it the value is set to true
:
Inputs
They are inputs that are always going to manage a model value different from a boolean
. In some occasions this can also be an array
or object
.
The available Web inputs are:
model
We can use the attribute value
to set the value:
Some inputs with complex model require the values properly stringified:
options
Some of the inputs, like CheckboxGroup
, CheckboxSelect
, Select
, or RadioSelect
have the options
attribute. This is a complex one that needs to be specified in a JSON stringified format.
These options can be individually disabled:
But alternately, <option>
tags in the default
slot can be use for better readability and SEO:
max-length
The TextInput
and Textarea
components allow the use of max-length
attribute.
No counter
We recommend to use the max-length
counter for UX purposes, but there are some instances where this counter might pollute the form too much. We strongly recommend to apply this only to TextInput
and not to Textarea
.
Wwe can use CSS:
css
z-text-input::part(output) {
display: none;
}
Or using the no-counter
flag for TextInput
:
Form inputs
Are inputs but with validation mechanisms.
The available Web form inputs are:
config
It's an attribute that defines the general style of the input:
Can also modify the general size:
placeholder
Most inputs can show a placeholder text when they are empty to show extra instructions.
readonly
Form inputs can used as outputs using the readonly
flag.
reset()
We can all the reset()
method of the WebComponent in order to reset the value. This will clean the internal states and emit the nullable value with the change
event, plus a restarted
event:
In this example, the button triggers the method:
Value:
undefined
Inputs validation
The validation of the inputs can be controlled using the invalid
flag. In combination with help-text
, you can also provide some feedback about the error.
Not every input has the invalid
option.
When the required
flag is set, the invalid state will be shown when the input is touched.
The message shown is this cases would be Required field
.
Attention!
invalid
is a HTML flag, that means that <z-input invalid="false"/>
will still be considered as invalid. If you're using a boolean to set the attribute, use a binding with an OR to undefined
.
The framework wrappers are managing this for you, so you can use pure booleans.
More info in flag.
Vue
v-model
Vue has the v-model
directive to manage the two-way data binding. But this comes with the twist of having to use specific naming for the value
attribute and the change
event, set as modelValue
and onUpdate:modelValue
respectively.
Here's an example of use:
vue
<script lang="ts" setup>
import { ref } from 'vue';
import { ZvCheckbox } from '@zurich/web-components/vue';
const value = ref(false);
</script>
<template>
<code><b>Value:</b> {{ value }}<code>
<zv-checkbox v-model="value"/>
</template>
An example of this in StackBlitz:
Angular
ngModel
Angular has the [(ngModel)]
directive to manage the two-way data binding. But this comes with the twist of having to use specific naming for the value
attribute and the change
event, that will be changed to ngModel
and ngModelChange
respectively.
You can use this naming without import FormsModule
due to the standardization done in our Angular wrappers.
Here's an example of use:
ts
import { Component } from '@angular/core';
import { ZaCheckbox } from '@zurich/angular-components';
@Component({
standalone: true,
imports: [ZaCheckbox],
template: `
<code><b>Value:</b> {{ value }}<code>
<za-checkbox [(ngModel)]="value"/>
`,
})
export class Checkbox {
value = false;
}
Reactive Forms
The components of @zurich/angular-components
are prepared to use Angular's Reactive Forms. The @angular/forms
package is already part of the dependencies
ts
import { CommonModule } from '@angular/common';
import { Component } from '@angular/core';
import { FormControl, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { ZaButton, ZaCheckboxSelect } from '@zurich/angular-components';
@Component({
standalone: true,
imports: [CommonModule, ZaCheckboxSelect, ZaButton, ReactiveFormsModule],
template: './app.component.html',
})
export class ReactiveForm {
readonly fruitOptions: ZaCheckboxSelect['options'] = [
{ text: 'Banana', value: 'banana' },
{ text: 'Orange', value: 'orange' },
{ text: 'Kiwi', value: 'kiwi' },
];
form = new FormGroup({
fruit: new FormControl(['banana']),
});
setValue() { this.form.controls.fruit.setValue(['kiwi']); }
resetValue() { this.form.controls.fruit.reset(); }
}
html
<form [formGroup]="form">
<za-checkbox-select label="Fruits" formControlName="fruit" [options]="fruitOptions"/>
<code><b>Value:</b> {{ form.get('fruit')?.value }}</code>
<div>
<za-button config="secondary:xs" (click)="setValue()">Set</za-button>
<za-button config="negative:xs" (click)="resetValue()">Reset</za-button>
</div>
</form>
An example of this in StackBlitz:
Attention!
We strongly recommend the use of encapsulation of forms with all the inputs being controlled via ReactiveFormsModule
in a single component. The combination of ReactiveFormsModule
and the use of [(ngModel)]
can lead to errors like:
shell
ERROR Error NG0201: No provider for NgControl found in NodeInjector.
This can be bypassed by adding FormsModule
to the imports
and the using the ngDefaultControl
attribute in the ZDS inputs that are using [(ngModel)]
. But we recommend not to use this approach, but the form encapsulation.