mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
feat(toggle): add required prop (#30156)
Issue number: resolves internal
---------
<!-- Please do not submit updates to dependencies unless it fixes an
issue. -->
<!-- Please try to limit your pull request to one type (bugfix, feature,
etc). Submit multiple pull requests if needed. -->
## What is the current behavior?
- Currently, the screen reader do not announce the component as required
when `required={true}`.
## What is the new behavior?
- Added a new `required` prop to be used for accessibility purposes that
adds the `required` attribute to toggle's inner native input.
## Does this introduce a breaking change?
- [ ] Yes
- [x] No
<!--
If this introduces a breaking change:
1. Describe the impact and migration path for existing applications
below.
2. Update the BREAKING.md file with the breaking change.
3. Add "BREAKING CHANGE: [...]" to the commit description when merging.
See
https://github.com/ionic-team/ionic-framework/blob/main/docs/CONTRIBUTING.md#footer
for more information.
-->
This commit is contained in:
@@ -1945,6 +1945,7 @@ ion-toggle,prop,justify,"end" | "space-between" | "start" | undefined,undefined,
|
||||
ion-toggle,prop,labelPlacement,"end" | "fixed" | "stacked" | "start",'start',false,false
|
||||
ion-toggle,prop,mode,"ios" | "md",undefined,false,false
|
||||
ion-toggle,prop,name,string,this.inputId,false,false
|
||||
ion-toggle,prop,required,boolean,false,false,false
|
||||
ion-toggle,prop,value,null | string | undefined,'on',false,false
|
||||
ion-toggle,event,ionBlur,void,true
|
||||
ion-toggle,event,ionChange,ToggleChangeEventDetail<any>,true
|
||||
|
||||
8
core/src/components.d.ts
vendored
8
core/src/components.d.ts
vendored
@@ -3284,6 +3284,10 @@ export namespace Components {
|
||||
* The name of the control, which is submitted with the form data.
|
||||
*/
|
||||
"name": string;
|
||||
/**
|
||||
* If true, screen readers will announce it as a required field. This property works only for accessibility purposes, it will not prevent the form from submitting if the value is invalid.
|
||||
*/
|
||||
"required": boolean;
|
||||
/**
|
||||
* The value of the toggle does not mean if it's checked or not, use the `checked` property for that. The value of a toggle is analogous to the value of a `<input type="checkbox">`, it's only used when the toggle participates in a native `<form>`.
|
||||
*/
|
||||
@@ -8163,6 +8167,10 @@ declare namespace LocalJSX {
|
||||
* Emitted when the toggle has focus.
|
||||
*/
|
||||
"onIonFocus"?: (event: IonToggleCustomEvent<void>) => void;
|
||||
/**
|
||||
* If true, screen readers will announce it as a required field. This property works only for accessibility purposes, it will not prevent the form from submitting if the value is invalid.
|
||||
*/
|
||||
"required"?: boolean;
|
||||
/**
|
||||
* The value of the toggle does not mean if it's checked or not, use the `checked` property for that. The value of a toggle is analogous to the value of a `<input type="checkbox">`, it's only used when the toggle participates in a native `<form>`.
|
||||
*/
|
||||
|
||||
@@ -75,3 +75,33 @@ describe('ion-toggle: disabled', () => {
|
||||
expect(toggle.checked).toBe(false);
|
||||
});
|
||||
});
|
||||
|
||||
describe('ion-toggle: required', () => {
|
||||
it('should have a required attribute in inner input when true', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Toggle],
|
||||
html: `
|
||||
<ion-toggle required="true">Toggle</ion-toggle>
|
||||
`,
|
||||
});
|
||||
|
||||
const toggle = page.body.querySelector('ion-toggle')!;
|
||||
const nativeInput = toggle.shadowRoot?.querySelector('input[role=switch]')!;
|
||||
|
||||
expect(nativeInput.hasAttribute('required')).toBeTruthy();
|
||||
});
|
||||
|
||||
it('should not have a required attribute in inner input when false', async () => {
|
||||
const page = await newSpecPage({
|
||||
components: [Toggle],
|
||||
html: `
|
||||
<ion-toggle required="false">Toggle</ion-toggle>
|
||||
`,
|
||||
});
|
||||
|
||||
const toggle = page.body.querySelector('ion-toggle')!;
|
||||
const nativeInput = toggle.shadowRoot?.querySelector('input[role=switch]')!;
|
||||
|
||||
expect(nativeInput.hasAttribute('required')).toBeFalsy();
|
||||
});
|
||||
});
|
||||
|
||||
@@ -108,6 +108,13 @@ export class Toggle implements ComponentInterface {
|
||||
*/
|
||||
@Prop() alignment?: 'start' | 'center';
|
||||
|
||||
/**
|
||||
* If true, screen readers will announce it as a required field. This property
|
||||
* works only for accessibility purposes, it will not prevent the form from
|
||||
* submitting if the value is invalid.
|
||||
*/
|
||||
@Prop() required = false;
|
||||
|
||||
/**
|
||||
* Emitted when the user switches the toggle on or off.
|
||||
*
|
||||
@@ -290,7 +297,8 @@ export class Toggle implements ComponentInterface {
|
||||
}
|
||||
|
||||
render() {
|
||||
const { activated, color, checked, disabled, el, justify, labelPlacement, inputId, name, alignment } = this;
|
||||
const { activated, color, checked, disabled, el, justify, labelPlacement, inputId, name, alignment, required } =
|
||||
this;
|
||||
|
||||
const mode = getIonMode(this);
|
||||
const value = this.getValue();
|
||||
@@ -327,6 +335,7 @@ export class Toggle implements ComponentInterface {
|
||||
onFocus={() => this.onFocus()}
|
||||
onBlur={() => this.onBlur()}
|
||||
ref={(focusEl) => (this.focusEl = focusEl)}
|
||||
required={required}
|
||||
{...this.inheritedAttributes}
|
||||
/>
|
||||
<div
|
||||
|
||||
@@ -2473,14 +2473,14 @@ Shorthand for ionToastDidDismiss.
|
||||
|
||||
|
||||
@ProxyCmp({
|
||||
inputs: ['alignment', 'checked', 'color', 'disabled', 'enableOnOffLabels', 'justify', 'labelPlacement', 'mode', 'name', 'value']
|
||||
inputs: ['alignment', 'checked', 'color', 'disabled', 'enableOnOffLabels', 'justify', 'labelPlacement', 'mode', 'name', 'required', 'value']
|
||||
})
|
||||
@Component({
|
||||
selector: 'ion-toggle',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: '<ng-content></ng-content>',
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||
inputs: ['alignment', 'checked', 'color', 'disabled', 'enableOnOffLabels', 'justify', 'labelPlacement', 'mode', 'name', 'value'],
|
||||
inputs: ['alignment', 'checked', 'color', 'disabled', 'enableOnOffLabels', 'justify', 'labelPlacement', 'mode', 'name', 'required', 'value'],
|
||||
})
|
||||
export class IonToggle {
|
||||
protected el: HTMLIonToggleElement;
|
||||
|
||||
@@ -1016,6 +1016,7 @@ export const IonToggle = /*@__PURE__*/ defineContainer<JSX.IonToggle, JSX.IonTog
|
||||
'labelPlacement',
|
||||
'justify',
|
||||
'alignment',
|
||||
'required',
|
||||
'ionChange',
|
||||
'ionFocus',
|
||||
'ionBlur'
|
||||
|
||||
Reference in New Issue
Block a user