mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2025-08-20 20:33:32 +08:00
feat(radio): add helperText and errorText properties
This commit is contained in:
@ -1323,6 +1323,8 @@ ion-radio,shadow
|
||||
ion-radio,prop,alignment,"center" | "start" | undefined,undefined,false,false
|
||||
ion-radio,prop,color,"danger" | "dark" | "light" | "medium" | "primary" | "secondary" | "success" | "tertiary" | "warning" | string & Record<never, never> | undefined,undefined,false,true
|
||||
ion-radio,prop,disabled,boolean,false,false,false
|
||||
ion-radio,prop,errorText,string | undefined,undefined,false,false
|
||||
ion-radio,prop,helperText,string | undefined,undefined,false,false
|
||||
ion-radio,prop,justify,"end" | "space-between" | "start" | undefined,undefined,false,false
|
||||
ion-radio,prop,labelPlacement,"end" | "fixed" | "stacked" | "start",'start',false,false
|
||||
ion-radio,prop,mode,"ios" | "md",undefined,false,false
|
||||
@ -1339,8 +1341,11 @@ ion-radio,css-prop,--color-checked,md
|
||||
ion-radio,css-prop,--inner-border-radius,ios
|
||||
ion-radio,css-prop,--inner-border-radius,md
|
||||
ion-radio,part,container
|
||||
ion-radio,part,error-text
|
||||
ion-radio,part,helper-text
|
||||
ion-radio,part,label
|
||||
ion-radio,part,mark
|
||||
ion-radio,part,supporting-text
|
||||
|
||||
ion-radio-group,none
|
||||
ion-radio-group,prop,allowEmptySelection,boolean,false,false,false
|
||||
|
16
core/src/components.d.ts
vendored
16
core/src/components.d.ts
vendored
@ -2267,6 +2267,14 @@ export namespace Components {
|
||||
* If `true`, the user cannot interact with the radio.
|
||||
*/
|
||||
"disabled": boolean;
|
||||
/**
|
||||
* Text that is placed under the radio and displayed when an error is detected.
|
||||
*/
|
||||
"errorText"?: string;
|
||||
/**
|
||||
* Text that is placed under the radio and displayed when no error is detected.
|
||||
*/
|
||||
"helperText"?: string;
|
||||
/**
|
||||
* How to pack the label and radio within a line. `"start"`: The label and radio will appear on the left in LTR and on the right in RTL. `"end"`: The label and radio will appear on the right in LTR and on the left in RTL. `"space-between"`: The label and radio will appear on opposite ends of the line with space between the two elements. Setting this property will change the radio `display` to `block`.
|
||||
*/
|
||||
@ -7017,6 +7025,14 @@ declare namespace LocalJSX {
|
||||
* If `true`, the user cannot interact with the radio.
|
||||
*/
|
||||
"disabled"?: boolean;
|
||||
/**
|
||||
* Text that is placed under the radio and displayed when an error is detected.
|
||||
*/
|
||||
"errorText"?: string;
|
||||
/**
|
||||
* Text that is placed under the radio and displayed when no error is detected.
|
||||
*/
|
||||
"helperText"?: string;
|
||||
/**
|
||||
* How to pack the label and radio within a line. `"start"`: The label and radio will appear on the left in LTR and on the right in RTL. `"end"`: The label and radio will appear on the right in LTR and on the left in RTL. `"space-between"`: The label and radio will appear on opposite ends of the line with space between the two elements. Setting this property will change the radio `display` to `block`.
|
||||
*/
|
||||
|
@ -140,6 +140,53 @@ input {
|
||||
align-items: center;
|
||||
}
|
||||
|
||||
// Radio Bottom Content
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
.radio-bottom {
|
||||
@include padding(5px, null, null, null);
|
||||
|
||||
display: flex;
|
||||
|
||||
justify-content: space-between;
|
||||
|
||||
font-size: dynamic-font(12px);
|
||||
|
||||
white-space: normal;
|
||||
}
|
||||
|
||||
:host(.radio-label-placement-stacked) .radio-bottom {
|
||||
font-size: dynamic-font(16px);
|
||||
}
|
||||
|
||||
// Radio Hint Text
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
/**
|
||||
* Error text should only be shown when .ion-invalid is
|
||||
* present on the checkbox. Otherwise the helper text should
|
||||
* be shown.
|
||||
*/
|
||||
.radio-bottom .error-text {
|
||||
display: none;
|
||||
|
||||
color: ion-color(danger, base);
|
||||
}
|
||||
|
||||
.radio-bottom .helper-text {
|
||||
display: block;
|
||||
|
||||
color: $text-color-step-300;
|
||||
}
|
||||
|
||||
:host(.ion-touched.ion-invalid) .radio-bottom .error-text {
|
||||
display: block;
|
||||
}
|
||||
|
||||
:host(.ion-touched.ion-invalid) .radio-bottom .helper-text {
|
||||
display: none;
|
||||
}
|
||||
|
||||
// Radio Label Placement - Start
|
||||
// ----------------------------------------------------------------
|
||||
|
||||
@ -213,6 +260,8 @@ input {
|
||||
*/
|
||||
:host(.radio-label-placement-stacked) .radio-wrapper {
|
||||
flex-direction: column;
|
||||
|
||||
text-align: center;
|
||||
}
|
||||
|
||||
:host(.radio-label-placement-stacked) .label-text-wrapper {
|
||||
|
@ -15,6 +15,9 @@ import type { Color } from '../../interface';
|
||||
* @part container - The container for the radio mark.
|
||||
* @part label - The label text describing the radio.
|
||||
* @part mark - The checkmark or dot used to indicate the checked state.
|
||||
* @part supporting-text - Supporting text displayed beneath the radio label.
|
||||
* @part helper-text - Supporting text displayed beneath the radio label when the radio is valid.
|
||||
* @part error-text - Supporting text displayed beneath the radio label when the radio is invalid and touched.
|
||||
*/
|
||||
@Component({
|
||||
tag: 'ion-radio',
|
||||
@ -26,6 +29,8 @@ import type { Color } from '../../interface';
|
||||
})
|
||||
export class Radio implements ComponentInterface {
|
||||
private inputId = `ion-rb-${radioButtonIds++}`;
|
||||
private helperTextId = `${this.inputId}-helper-text`;
|
||||
private errorTextId = `${this.inputId}-error-text`;
|
||||
private radioGroup: HTMLIonRadioGroupElement | null = null;
|
||||
|
||||
@Element() el!: HTMLIonRadioElement;
|
||||
@ -58,6 +63,16 @@ export class Radio implements ComponentInterface {
|
||||
*/
|
||||
@Prop() disabled = false;
|
||||
|
||||
/**
|
||||
* Text that is placed under the radio and displayed when an error is detected.
|
||||
*/
|
||||
@Prop() errorText?: string;
|
||||
|
||||
/**
|
||||
* Text that is placed under the radio and displayed when no error is detected.
|
||||
*/
|
||||
@Prop() helperText?: string;
|
||||
|
||||
/**
|
||||
* the value of the radio.
|
||||
*/
|
||||
@ -212,6 +227,48 @@ export class Radio implements ComponentInterface {
|
||||
);
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
/**
|
||||
* Responsible for rendering helper text and error text.
|
||||
* This element should only be rendered if hint text is set.
|
||||
*/
|
||||
private renderHintText() {
|
||||
const { helperText, errorText, helperTextId, errorTextId } = this;
|
||||
|
||||
/**
|
||||
* undefined and empty string values should
|
||||
* be treated as not having helper/error text.
|
||||
*/
|
||||
const hasHintText = !!helperText || !!errorText;
|
||||
if (!hasHintText) {
|
||||
return;
|
||||
}
|
||||
|
||||
return (
|
||||
<div class="radio-bottom">
|
||||
<div id={helperTextId} class="helper-text" part="supporting-text helper-text">
|
||||
{helperText}
|
||||
</div>
|
||||
<div id={errorTextId} class="error-text" part="supporting-text error-text">
|
||||
{errorText}
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
render() {
|
||||
const { checked, disabled, color, el, justify, labelPlacement, hasLabel, buttonTabindex, alignment } = this;
|
||||
const mode = getIonMode(this);
|
||||
@ -237,6 +294,8 @@ export class Radio implements ComponentInterface {
|
||||
role="radio"
|
||||
aria-checked={checked ? 'true' : 'false'}
|
||||
aria-disabled={disabled ? 'true' : null}
|
||||
aria-describedby={this.getHintTextID()}
|
||||
aria-invalid={this.getHintTextID() === this.errorTextId}
|
||||
tabindex={buttonTabindex}
|
||||
>
|
||||
<label class="radio-wrapper">
|
||||
@ -248,6 +307,7 @@ export class Radio implements ComponentInterface {
|
||||
part="label"
|
||||
>
|
||||
<slot></slot>
|
||||
{this.renderHintText()}
|
||||
</div>
|
||||
<div class="native-wrapper">{this.renderRadioControl()}</div>
|
||||
</label>
|
||||
|
@ -1607,14 +1607,14 @@ export declare interface IonProgressBar extends Components.IonProgressBar {}
|
||||
|
||||
|
||||
@ProxyCmp({
|
||||
inputs: ['alignment', 'color', 'disabled', 'justify', 'labelPlacement', 'mode', 'name', 'value']
|
||||
inputs: ['alignment', 'color', 'disabled', 'errorText', 'helperText', 'justify', 'labelPlacement', 'mode', 'name', 'value']
|
||||
})
|
||||
@Component({
|
||||
selector: 'ion-radio',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: '<ng-content></ng-content>',
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||
inputs: ['alignment', 'color', 'disabled', 'justify', 'labelPlacement', 'mode', 'name', 'value'],
|
||||
inputs: ['alignment', 'color', 'disabled', 'errorText', 'helperText', 'justify', 'labelPlacement', 'mode', 'name', 'value'],
|
||||
})
|
||||
export class IonRadio {
|
||||
protected el: HTMLElement;
|
||||
|
@ -1614,14 +1614,14 @@ export declare interface IonProgressBar extends Components.IonProgressBar {}
|
||||
|
||||
@ProxyCmp({
|
||||
defineCustomElementFn: defineIonRadio,
|
||||
inputs: ['alignment', 'color', 'disabled', 'justify', 'labelPlacement', 'mode', 'name', 'value']
|
||||
inputs: ['alignment', 'color', 'disabled', 'errorText', 'helperText', 'justify', 'labelPlacement', 'mode', 'name', 'value']
|
||||
})
|
||||
@Component({
|
||||
selector: 'ion-radio',
|
||||
changeDetection: ChangeDetectionStrategy.OnPush,
|
||||
template: '<ng-content></ng-content>',
|
||||
// eslint-disable-next-line @angular-eslint/no-inputs-metadata-property
|
||||
inputs: ['alignment', 'color', 'disabled', 'justify', 'labelPlacement', 'mode', 'name', 'value'],
|
||||
inputs: ['alignment', 'color', 'disabled', 'errorText', 'helperText', 'justify', 'labelPlacement', 'mode', 'name', 'value'],
|
||||
standalone: true
|
||||
})
|
||||
export class IonRadio {
|
||||
|
@ -612,6 +612,8 @@ export const IonRadio = /*@__PURE__*/ defineContainer<JSX.IonRadio, JSX.IonRadio
|
||||
'color',
|
||||
'name',
|
||||
'disabled',
|
||||
'errorText',
|
||||
'helperText',
|
||||
'value',
|
||||
'labelPlacement',
|
||||
'justify',
|
||||
|
Reference in New Issue
Block a user