Skip to content

Commit def00f6

Browse files
committed
docs(toggle): add helperText and errorText section
1 parent e2f96bf commit def00f6

8 files changed

Lines changed: 274 additions & 0 deletions

File tree

docs/api/toggle.md

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -73,6 +73,16 @@ import Justify from '@site/static/usage/v8/toggle/justify/index.md';
7373

7474
<Justify />
7575

76+
## Helper & Error Text
77+
78+
Helper and error text can be used inside of a toggle with the `helperText` and `errorText` property. The error text will not be displayed unless the `ion-invalid` and `ion-touched` classes are added to the `ion-toggle`. This ensures errors are not shown before the user has a chance to enter data.
79+
80+
In Angular, this is done automatically through form validation. In JavaScript, React and Vue, the class needs to be manually added based on your own validation.
81+
82+
import HelperError from '@site/static/usage/v8/toggle/helper-error/index.md';
83+
84+
<HelperError />
85+
7686
## Theming
7787

7888
### Colors
Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
```html
2+
<form [formGroup]="myForm" (ngSubmit)="onSubmit()">
3+
<ion-toggle formControlName="wifi" helperText="This needs to be enabled" errorText="This field is required">
4+
Wi-Fi
5+
</ion-toggle>
6+
7+
<br />
8+
9+
<ion-button type="submit" size="small">Submit</ion-button>
10+
</form>
11+
```
Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
```ts
2+
import { Component } from '@angular/core';
3+
import { FormBuilder, FormGroup, Validators, ReactiveFormsModule } from '@angular/forms';
4+
import { IonToggle, IonButton } from '@ionic/angular/standalone';
5+
6+
@Component({
7+
selector: 'app-example',
8+
standalone: true,
9+
imports: [IonToggle, IonButton, ReactiveFormsModule],
10+
templateUrl: './example.component.html',
11+
styleUrl: './example.component.css',
12+
})
13+
export class ExampleComponent {
14+
myForm: FormGroup;
15+
16+
constructor(private fb: FormBuilder) {
17+
this.myForm = this.fb.group({
18+
wifi: [false, Validators.requiredTrue],
19+
});
20+
}
21+
22+
onSubmit() {
23+
// Mark the control as touched to trigger the error message.
24+
// This is needed if the user submits the form without interacting
25+
// with the toggle.
26+
this.myForm.get('wifi')!.markAsTouched();
27+
}
28+
}
29+
```
Lines changed: 58 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,58 @@
1+
<!DOCTYPE html>
2+
<html lang="en">
3+
<head>
4+
<meta charset="UTF-8" />
5+
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
6+
<title>Input</title>
7+
<link rel="stylesheet" href="../../common.css" />
8+
<script src="../../common.js"></script>
9+
<script
10+
type="module"
11+
src="https://cdn.jsdelivr.net/npm/@ionic/core@8/dist/ionic/ionic.esm.js"
12+
></script>
13+
<link
14+
rel="stylesheet"
15+
href="https://cdn.jsdelivr.net/npm/@ionic/core@8/css/ionic.bundle.css"
16+
/>
17+
</head>
18+
19+
<body>
20+
<div class="container">
21+
<form id="my-form">
22+
<ion-toggle helper-text="This needs to be enabled" error-text="This field is required">
23+
Wi-Fi
24+
</ion-toggle>
25+
26+
<br />
27+
28+
<ion-button type="submit" size="small">Submit</ion-button>
29+
</form>
30+
</div>
31+
32+
<script>
33+
const form = document.getElementById('my-form');
34+
const wifi = form.querySelector('ion-toggle');
35+
36+
form.addEventListener('submit', (event) => submit(event));
37+
wifi.addEventListener('ionChange', (event) => validateToggle(event));
38+
39+
const validateToggle = (event) => {
40+
wifi.classList.add('ion-touched');
41+
42+
if (!event.detail.checked) {
43+
wifi.classList.add('ion-invalid');
44+
wifi.classList.remove('ion-valid');
45+
} else {
46+
wifi.classList.remove('ion-invalid');
47+
wifi.classList.add('ion-valid');
48+
}
49+
};
50+
51+
const submit = (event) => {
52+
event.preventDefault();
53+
54+
validateToggle({ detail: { checked: wifi.checked } });
55+
};
56+
</script>
57+
</body>
58+
</html>
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
import Playground from '@site/src/components/global/Playground';
2+
3+
import javascript from './javascript.md';
4+
import react from './react.md';
5+
import vue from './vue.md';
6+
7+
import angular_example_component_html from './angular/example_component_html.md';
8+
import angular_example_component_ts from './angular/example_component_ts.md';
9+
10+
<Playground
11+
version="8"
12+
code={{
13+
javascript,
14+
react,
15+
vue,
16+
angular: {
17+
files: {
18+
'src/app/example.component.html': angular_example_component_html,
19+
'src/app/example.component.ts': angular_example_component_ts,
20+
},
21+
},
22+
}}
23+
src="usage/v8/toggle/helper-error/demo.html"
24+
/>
Lines changed: 37 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,37 @@
1+
```html
2+
<form id="my-form">
3+
<ion-toggle helper-text="This needs to be enabled" error-text="This field is required">
4+
Wi-Fi
5+
</ion-toggle>
6+
7+
<br />
8+
9+
<ion-button type="submit" size="small">Submit</ion-button>
10+
</form>
11+
12+
<script>
13+
const form = document.getElementById('my-form');
14+
const wifi = form.querySelector('ion-toggle');
15+
16+
form.addEventListener('submit', (event) => submit(event));
17+
wifi.addEventListener('ionChange', (event) => validateToggle(event));
18+
19+
const validateToggle = (event) => {
20+
wifi.classList.add('ion-touched');
21+
22+
if (!event.detail.checked) {
23+
wifi.classList.add('ion-invalid');
24+
wifi.classList.remove('ion-valid');
25+
} else {
26+
wifi.classList.remove('ion-invalid');
27+
wifi.classList.add('ion-valid');
28+
}
29+
};
30+
31+
const submit = (event) => {
32+
event.preventDefault();
33+
34+
validateToggle({ detail: { checked: wifi.checked } });
35+
};
36+
</script>
37+
```
Lines changed: 52 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,52 @@
1+
```tsx
2+
import React, { useRef, useState } from 'react';
3+
import { IonToggle, IonButton, ToggleCustomEvent } from '@ionic/react';
4+
5+
function Example() {
6+
const [isTouched, setIsTouched] = useState<boolean>(false);
7+
const [isValid, setIsValid] = useState<boolean | undefined>();
8+
9+
const wifiRef = useRef<HTMLIonToggleElement>(null);
10+
11+
const validateToggle = (event: ToggleCustomEvent<{ checked: boolean }>) => {
12+
setIsTouched(true);
13+
setIsValid(event.detail.checked);
14+
};
15+
16+
const submit = (event: React.FormEvent<HTMLFormElement>) => {
17+
event.preventDefault();
18+
19+
if (wifiRef.current) {
20+
validateToggle({ detail: { checked: wifiRef.current.checked } } as ToggleCustomEvent<{
21+
checked: boolean;
22+
}>);
23+
}
24+
};
25+
26+
return (
27+
<>
28+
<form onSubmit={submit}>
29+
<IonToggle
30+
ref={wifiRef}
31+
className={`${isValid ? 'ion-valid' : ''} ${isValid === false ? 'ion-invalid' : ''} ${
32+
isTouched ? 'ion-touched' : ''
33+
}`}
34+
helperText="This needs to be enabled"
35+
errorText="This field is required"
36+
onIonChange={(event) => validateToggle(event)}
37+
>
38+
I agree to the terms and conditions
39+
</IonToggle>
40+
41+
<br />
42+
43+
<IonButton type="submit" size="small">
44+
Submit
45+
</IonButton>
46+
</form>
47+
</>
48+
);
49+
}
50+
51+
export default Example;
52+
```
Lines changed: 53 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,53 @@
1+
```html
2+
<template>
3+
<form @submit.prevent="submit">
4+
<ion-toggle
5+
v-model="wifi"
6+
helper-text="This needs to be enabled"
7+
error-text="This field is required"
8+
@ionChange="validateToggle"
9+
:class="{ 'ion-valid': isValid, 'ion-invalid': isValid === false, 'ion-touched': isTouched }"
10+
>
11+
Wi-Fi
12+
</ion-toggle>
13+
14+
<br />
15+
16+
<ion-button type="submit" size="small">Submit</ion-button>
17+
</form>
18+
</template>
19+
20+
<script lang="ts">
21+
import { defineComponent, ref } from 'vue';
22+
import { IonToggle, IonButton, ToggleCustomEvent } from '@ionic/vue';
23+
24+
export default defineComponent({
25+
components: {
26+
IonToggle,
27+
IonButton,
28+
},
29+
setup() {
30+
const wifi = ref(false);
31+
const isTouched = ref(false);
32+
const isValid = ref<boolean | undefined>();
33+
34+
const validateToggle = (event: ToggleCustomEvent<{ checked: boolean }>) => {
35+
isTouched.value = true;
36+
isValid.value = event.detail.checked;
37+
};
38+
39+
const submit = () => {
40+
validateToggle({ detail: { checked: wifi.value } } as ToggleCustomEvent<{ checked: boolean }>);
41+
};
42+
43+
return {
44+
wifi,
45+
isTouched,
46+
isValid,
47+
validateToggle,
48+
submit,
49+
};
50+
},
51+
});
52+
</script>
53+
```

0 commit comments

Comments
 (0)