feat(radio-group): add helperText and errorText properties

This commit is contained in:
Brandy Smith
2025-02-27 14:20:59 -05:00
parent 41da4c3565
commit 0827a4cffe
7 changed files with 150 additions and 3 deletions

View File

@ -2307,6 +2307,14 @@ export namespace Components {
* This property allows developers to specify a custom function or property name for comparing objects when determining the selected option in the ion-radio-group. When not specified, the default behavior will use strict equality (===) for comparison.
*/
"compareWith"?: string | RadioGroupCompareFn | null;
/**
* The error text to display at the top of the radio group.
*/
"errorText"?: string;
/**
* The helper text to display at the top of the radio group.
*/
"helperText"?: string;
/**
* The name of the control, which is submitted with the form data.
*/
@ -7079,6 +7087,14 @@ declare namespace LocalJSX {
* This property allows developers to specify a custom function or property name for comparing objects when determining the selected option in the ion-radio-group. When not specified, the default behavior will use strict equality (===) for comparison.
*/
"compareWith"?: string | RadioGroupCompareFn | null;
/**
* The error text to display at the top of the radio group.
*/
"errorText"?: string;
/**
* The helper text to display at the top of the radio group.
*/
"helperText"?: string;
/**
* The name of the control, which is submitted with the form data.
*/

View File

@ -0,0 +1,12 @@
@import "../../themes/ionic.globals.ios";
@import "./radio-group";
@import "../item/item.ios.vars";
// iOS Radio Group in List
// --------------------------------------------------
// Add padding to the error and helper text when used in a
// list to align them with the list header and item text.
ion-list .supporting-text {
@include padding-horizontal($item-ios-padding-start, $item-ios-padding-end);
}

View File

@ -0,0 +1,12 @@
@import "../../themes/ionic.globals.md";
@import "./radio-group";
@import "../item/item.md.vars";
// Material Design Radio Group in List
// --------------------------------------------------
// Add padding to the error and helper text when used in a
// list to align them with the list header and item text.
ion-list .supporting-text {
@include padding-horizontal($item-md-padding-start, $item-md-padding-end);
}

View File

@ -0,0 +1,40 @@
@import "../../themes/ionic.globals";
// Radio Group
// --------------------------------------------------
ion-radio-group {
display: block;
}
// Radio Group: Supporting Text
// --------------------------------------------------
.supporting-text {
line-height: 1.5;
}
/**
* Error text should only be shown when .ion-invalid is
* present on the radio group. Otherwise the helper text should
* be shown.
*/
.error-text {
display: none;
color: var(--ion-color-danger, #eb445a);
}
.helper-text {
display: block;
color: var(--ion-color-step-550, #737373);
}
.ion-touched.ion-invalid .error-text {
display: block;
}
.ion-touched.ion-invalid .helper-text {
display: none;
}

View File

@ -8,9 +8,15 @@ import type { RadioGroupChangeEventDetail, RadioGroupCompareFn } from './radio-g
@Component({
tag: 'ion-radio-group',
styleUrls: {
ios: 'radio-group.ios.scss',
md: 'radio-group.md.scss',
},
})
export class RadioGroup implements ComponentInterface {
private inputId = `ion-rg-${radioGroupIds++}`;
private helperTextId = `${this.inputId}-helper-text`;
private errorTextId = `${this.inputId}-error-text`;
private labelId = `${this.inputId}-lbl`;
private label?: HTMLIonLabelElement | null;
@ -39,6 +45,16 @@ export class RadioGroup implements ComponentInterface {
*/
@Prop({ mutable: true }) value?: any | null;
/**
* The helper text to display at the top of the radio group.
*/
@Prop() helperText?: string;
/**
* The error text to display at the top of the radio group.
*/
@Prop() errorText?: string;
@Watch('value')
valueChanged(value: any | undefined) {
this.setRadioTabindex(value);
@ -224,13 +240,62 @@ export class RadioGroup implements ComponentInterface {
radioToFocus?.setFocus();
}
/**
* Renders the helper text or error text values
*/
private renderHintText() {
const { helperText, errorText, helperTextId, errorTextId } = this;
const hasHintText = !!helperText || !!errorText;
if (!hasHintText) {
return;
}
return (
<div class="supporting-text">
<div id={helperTextId} class="helper-text">
{helperText}
</div>
<div id={errorTextId} class="error-text">
{errorText}
</div>
</div>
);
}
private getHintTextID(): string | undefined {
const { el, helperText, errorText, helperTextId, errorTextId } = this;
if (el.classList.contains('ion-touched') && el.classList.contains('ion-invalid') && errorText) {
return errorTextId;
}
if (helperText) {
return helperTextId;
}
return undefined;
}
render() {
const { label, labelId, el, name, value } = this;
const mode = getIonMode(this);
renderHiddenInput(true, el, name, value, false);
return <Host role="radiogroup" aria-labelledby={label ? labelId : null} onClick={this.onClick} class={mode}></Host>;
return (
<Host
role="radiogroup"
aria-labelledby={label ? labelId : null}
aria-describedby={this.getHintTextID()}
aria-invalid={this.getHintTextID() === this.errorTextId}
onClick={this.onClick}
class={mode}
>
{this.renderHintText()}
<slot></slot>
</Host>
);
}
}

View File

@ -1639,14 +1639,14 @@ export declare interface IonRadio extends Components.IonRadio {
@ProxyCmp({
inputs: ['allowEmptySelection', 'compareWith', 'name', 'value']
inputs: ['allowEmptySelection', 'compareWith', 'errorText', 'helperText', 'name', 'value']
})
@Component({
selector: 'ion-radio-group',
changeDetection: ChangeDetectionStrategy.OnPush,
template: '<ng-content></ng-content>',
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
inputs: ['allowEmptySelection', 'compareWith', 'name', 'value'],
inputs: ['allowEmptySelection', 'compareWith', 'errorText', 'helperText', 'name', 'value'],
})
export class IonRadioGroup {
protected el: HTMLIonRadioGroupElement;

View File

@ -696,6 +696,8 @@ export const IonRadioGroup = /*@__PURE__*/ defineContainer<JSX.IonRadioGroup, JS
'compareWith',
'name',
'value',
'helperText',
'errorText',
'ionChange',
'ionValueChange'
], [