mirror of
https://github.com/ionic-team/ionic-framework.git
synced 2026-03-13 10:22:08 +08:00
Compare commits
2 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
f04fa23e0d | ||
|
|
ce83407e1d |
@@ -127,6 +127,8 @@ export class Checkbox implements ComponentInterface {
|
||||
*/
|
||||
@State() isInvalid = false;
|
||||
|
||||
@State() private hasLabelContent = false;
|
||||
|
||||
@State() private hintTextId?: string;
|
||||
|
||||
/**
|
||||
@@ -265,6 +267,10 @@ export class Checkbox implements ComponentInterface {
|
||||
ev.stopPropagation();
|
||||
};
|
||||
|
||||
private onSlotChange = () => {
|
||||
this.hasLabelContent = this.el.textContent !== '';
|
||||
};
|
||||
|
||||
private getHintTextId(): string | undefined {
|
||||
const { helperText, errorText, helperTextId, errorTextId, isInvalid } = this;
|
||||
|
||||
@@ -326,7 +332,6 @@ export class Checkbox implements ComponentInterface {
|
||||
} = this;
|
||||
const mode = getIonMode(this);
|
||||
const path = getSVGPath(mode, indeterminate);
|
||||
const hasLabelContent = el.textContent !== '';
|
||||
|
||||
renderHiddenInput(true, el, name, checked ? value : '', disabled);
|
||||
|
||||
@@ -338,7 +343,7 @@ export class Checkbox implements ComponentInterface {
|
||||
aria-checked={indeterminate ? 'mixed' : `${checked}`}
|
||||
aria-describedby={this.hintTextId}
|
||||
aria-invalid={this.isInvalid ? 'true' : undefined}
|
||||
aria-labelledby={hasLabelContent ? this.inputLabelId : null}
|
||||
aria-labelledby={this.hasLabelContent ? this.inputLabelId : null}
|
||||
aria-label={inheritedAttributes['aria-label'] || null}
|
||||
aria-disabled={disabled ? 'true' : null}
|
||||
aria-required={required ? 'true' : undefined}
|
||||
@@ -376,13 +381,13 @@ export class Checkbox implements ComponentInterface {
|
||||
<div
|
||||
class={{
|
||||
'label-text-wrapper': true,
|
||||
'label-text-wrapper-hidden': !hasLabelContent,
|
||||
'label-text-wrapper-hidden': !this.hasLabelContent,
|
||||
}}
|
||||
part="label"
|
||||
id={this.inputLabelId}
|
||||
onClick={this.onDivLabelClick}
|
||||
>
|
||||
<slot></slot>
|
||||
<slot onSlotchange={this.onSlotChange}></slot>
|
||||
{this.renderHintText()}
|
||||
</div>
|
||||
<div class="native-wrapper">
|
||||
|
||||
@@ -8,13 +8,19 @@ test.describe('Value Accessors', () => {
|
||||
|
||||
test('should update the form value', async ({ page }) => {
|
||||
await expect(page.locator('#formValue')).toHaveText(JSON.stringify({ checkbox: false }, null, 2));
|
||||
await expect(page.locator('ion-checkbox')).toHaveClass(/ion-pristine/);
|
||||
await expect(page.getByRole('checkbox', { name: 'Static Checkbox Label' })).toHaveClass(/ion-pristine/);
|
||||
|
||||
await page.locator('ion-checkbox').click();
|
||||
await page.getByRole('checkbox', { name: 'Static Checkbox Label' }).click();
|
||||
|
||||
await expect(page.locator('#formValue')).toHaveText(JSON.stringify({ checkbox: true }, null, 2));
|
||||
await expect(page.locator('ion-checkbox')).toHaveClass(/ion-dirty/);
|
||||
await expect(page.locator('ion-checkbox')).toHaveClass(/ion-valid/);
|
||||
await expect(page.getByRole('checkbox', { name: 'Static Checkbox Label' })).toHaveClass(/ion-dirty/);
|
||||
await expect(page.getByRole('checkbox', { name: 'Static Checkbox Label' })).toHaveClass(/ion-valid/);
|
||||
|
||||
await expect(page.getByRole('checkbox', { name: 'Static Checkbox Label' })).toBeVisible();
|
||||
});
|
||||
|
||||
test('should display dynamically set label', async ({ page }) => {
|
||||
await expect(page.getByRole('checkbox', { name: 'Dynamic Checkbox Label' })).toBeVisible();
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
@@ -28,7 +28,6 @@ import { AlertComponent } from '../alert/alert.component';
|
||||
import { AccordionComponent } from '../accordion/accordion.component';
|
||||
import { AccordionModalComponent } from '../accordion/accordion-modal/accordion-modal.component';
|
||||
import { TabsBasicComponent } from '../tabs-basic/tabs-basic.component';
|
||||
import { TemplateFormComponent } from '../template-form/template-form.component';
|
||||
|
||||
@NgModule({
|
||||
declarations: [
|
||||
@@ -54,8 +53,7 @@ import { TemplateFormComponent } from '../template-form/template-form.component'
|
||||
AlertComponent,
|
||||
AccordionComponent,
|
||||
AccordionModalComponent,
|
||||
TabsBasicComponent,
|
||||
TemplateFormComponent
|
||||
TabsBasicComponent
|
||||
],
|
||||
imports: [
|
||||
CommonModule,
|
||||
|
||||
@@ -19,7 +19,6 @@ import { NavigationPage3Component } from '../navigation-page3/navigation-page3.c
|
||||
import { AlertComponent } from '../alert/alert.component';
|
||||
import { AccordionComponent } from '../accordion/accordion.component';
|
||||
import { TabsBasicComponent } from '../tabs-basic/tabs-basic.component';
|
||||
import { TemplateFormComponent } from '../template-form/template-form.component';
|
||||
|
||||
export const routes: Routes = [
|
||||
{
|
||||
@@ -34,7 +33,7 @@ export const routes: Routes = [
|
||||
{ path: 'textarea', loadChildren: () => import('../textarea/textarea.module').then(m => m.TextareaModule) },
|
||||
{ path: 'searchbar', loadChildren: () => import('../searchbar/searchbar.module').then(m => m.SearchbarModule) },
|
||||
{ path: 'form', component: FormComponent },
|
||||
{ path: 'template-form', component: TemplateFormComponent },
|
||||
{ path: 'template-form', loadChildren: () => import('../template-form/template-form.module').then(m => m.TemplateFormModule) },
|
||||
{ path: 'modals', component: ModalComponent },
|
||||
{ path: 'modal-inline', loadChildren: () => import('../modal-inline').then(m => m.ModalInlineModule) },
|
||||
{ path: 'modal-sheet-inline', loadChildren: () => import('../modal-sheet-inline').then(m => m.ModalSheetInlineModule) },
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
import { NgModule } from "@angular/core";
|
||||
import { RouterModule } from "@angular/router";
|
||||
import { TemplateFormComponent } from "./template-form.component";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
RouterModule.forChild([
|
||||
{
|
||||
path: '',
|
||||
component: TemplateFormComponent
|
||||
}
|
||||
])
|
||||
],
|
||||
exports: [RouterModule]
|
||||
})
|
||||
export class TemplateFormRoutingModule { }
|
||||
@@ -109,6 +109,7 @@
|
||||
[(ngModel)]="checkboxValue"
|
||||
name="checkboxField"
|
||||
required
|
||||
requireTrue
|
||||
#checkboxField="ngModel"
|
||||
id="template-checkbox-test"
|
||||
helper-text="You must agree to continue"
|
||||
@@ -133,6 +134,7 @@
|
||||
[(ngModel)]="toggleValue"
|
||||
name="toggleField"
|
||||
required
|
||||
requireTrue
|
||||
#toggleField="ngModel"
|
||||
id="template-toggle-test"
|
||||
helper-text="You must turn on to continue"
|
||||
|
||||
@@ -0,0 +1,23 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { NgModule } from "@angular/core";
|
||||
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||
import { IonicModule } from "@ionic/angular";
|
||||
|
||||
import { TemplateFormRoutingModule } from "./template-form-routing.module";
|
||||
import { TemplateFormComponent } from "./template-form.component";
|
||||
import { ValidatorsModule } from "../validators/validators.module";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule,
|
||||
IonicModule,
|
||||
TemplateFormRoutingModule,
|
||||
ValidatorsModule
|
||||
],
|
||||
declarations: [
|
||||
TemplateFormComponent
|
||||
]
|
||||
})
|
||||
export class TemplateFormModule { }
|
||||
@@ -0,0 +1,19 @@
|
||||
import { Directive, forwardRef } from '@angular/core';
|
||||
import { NG_VALIDATORS, Validator, AbstractControl, ValidationErrors, Validators } from '@angular/forms';
|
||||
|
||||
@Directive({
|
||||
selector: '[requireTrue]',
|
||||
providers: [
|
||||
{
|
||||
provide: NG_VALIDATORS,
|
||||
useExisting: forwardRef(() => RequireTrueValidatorDirective),
|
||||
multi: true,
|
||||
},
|
||||
],
|
||||
standalone: false,
|
||||
})
|
||||
export class RequireTrueValidatorDirective implements Validator {
|
||||
validate(control: AbstractControl): ValidationErrors | null {
|
||||
return Validators.requiredTrue(control);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
import { CommonModule } from "@angular/common";
|
||||
import { NgModule } from "@angular/core";
|
||||
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
|
||||
|
||||
import { RequireTrueValidatorDirective } from "./require-true.directive";
|
||||
|
||||
@NgModule({
|
||||
imports: [
|
||||
CommonModule,
|
||||
FormsModule,
|
||||
ReactiveFormsModule
|
||||
],
|
||||
declarations: [
|
||||
RequireTrueValidatorDirective
|
||||
],
|
||||
exports: [
|
||||
RequireTrueValidatorDirective
|
||||
]
|
||||
})
|
||||
export class ValidatorsModule { }
|
||||
@@ -6,6 +6,7 @@
|
||||
</p>
|
||||
|
||||
<app-value-accessor-test [formGroup]="form">
|
||||
<ion-checkbox formControlName="checkbox">Checkbox</ion-checkbox>
|
||||
<ion-checkbox formControlName="checkbox">Static Checkbox Label</ion-checkbox>
|
||||
</app-value-accessor-test>
|
||||
<ion-checkbox>{{dynamicLabel}}</ion-checkbox>
|
||||
</div>
|
||||
|
||||
@@ -15,6 +15,11 @@ import { ValueAccessorTestComponent } from "../value-accessor-test/value-accesso
|
||||
]
|
||||
})
|
||||
export class CheckboxComponent {
|
||||
dynamicLabel = '';
|
||||
|
||||
ngAfterViewInit(): void {
|
||||
this.dynamicLabel = 'Dynamic Checkbox Label';
|
||||
}
|
||||
|
||||
form = this.fb.group({
|
||||
checkbox: [false, Validators.required],
|
||||
|
||||
Reference in New Issue
Block a user