1
0
mirror of https://github.com/bitwarden/browser synced 2025-12-06 00:13:28 +00:00

[CL-735][CL-743] Finish migrating form control components to signals (#15927)

This commit is contained in:
Vicki League
2025-08-22 15:17:14 -04:00
committed by GitHub
parent 7bcd85314e
commit dd4ec9c5d9
3 changed files with 58 additions and 45 deletions

View File

@@ -1,4 +1,4 @@
import { Component, HostBinding, Input, Optional, Self } from "@angular/core";
import { booleanAttribute, Component, HostBinding, input, Optional, Self } from "@angular/core";
import { NgControl, Validators } from "@angular/forms";
import { BitFormControlAbstraction } from "../form-control";
@@ -7,6 +7,9 @@ import { BitFormControlAbstraction } from "../form-control";
selector: "input[type=checkbox][bitCheckbox]",
template: "",
providers: [{ provide: BitFormControlAbstraction, useExisting: CheckboxComponent }],
host: {
"[disabled]": "disabled",
},
})
export class CheckboxComponent implements BitFormControlAbstraction {
@HostBinding("class")
@@ -105,30 +108,17 @@ export class CheckboxComponent implements BitFormControlAbstraction {
protected indeterminateImage =
`url('data:image/svg+xml,%3Csvg xmlns="http://www.w3.org/2000/svg" width="14" height="14" fill="none" viewBox="0 0 13 13"%3E%3Cpath stroke="%23fff" stroke-width="2" d="M2.5 6.5h8"/%3E%3C/svg%3E%0A')`;
// TODO: Skipped for signal migration because:
// Accessor inputs cannot be migrated as they are too complex.
@HostBinding()
@Input()
get disabled() {
return this._disabled ?? this.ngControl?.disabled ?? false;
}
set disabled(value: any) {
this._disabled = value != null && value !== false;
}
private _disabled?: boolean;
readonly disabledInput = input(false, { transform: booleanAttribute, alias: "disabled" });
// TODO migrate to computed signal when Angular adds signal support to reactive forms
// https://bitwarden.atlassian.net/browse/CL-819
get disabled() {
return this.disabledInput() || this.ngControl?.disabled || false;
}
// TODO: Skipped for signal migration because:
// Accessor inputs cannot be migrated as they are too complex.
@Input()
get required() {
return (
this._required ?? this.ngControl?.control?.hasValidator(Validators.requiredTrue) ?? false
);
return this.ngControl?.control?.hasValidator(Validators.requiredTrue) ?? false;
}
set required(value: any) {
this._required = value != null && value !== false;
}
private _required?: boolean;
get hasError() {
return !!(this.ngControl?.status === "INVALID" && this.ngControl?.touched);

View File

@@ -1,4 +1,10 @@
import { FormsModule, ReactiveFormsModule, FormControl, FormGroup } from "@angular/forms";
import {
FormsModule,
ReactiveFormsModule,
FormControl,
FormGroup,
Validators,
} from "@angular/forms";
import { Meta, moduleMetadata, StoryObj } from "@storybook/angular";
import { I18nService } from "@bitwarden/common/platform/abstractions/i18n.service";
@@ -165,6 +171,35 @@ export const BlockHint: Story = {
}),
};
export const Required: Story = {
render: () => ({
props: {
formObj: new FormGroup({
radio: new FormControl(0, Validators.required),
}),
},
template: /* HTML */ `
<form [formGroup]="formObj">
<bit-radio-group formControlName="radio" aria-label="Example radio group">
<bit-label>Group of radio buttons</bit-label>
<bit-radio-button [value]="0">
<bit-label>First</bit-label>
</bit-radio-button>
<bit-radio-button [value]="1">
<bit-label>Second</bit-label>
</bit-radio-button>
<bit-radio-button [value]="2">
<bit-label>Third</bit-label>
</bit-radio-button>
</bit-radio-group>
</form>
`,
}),
};
export const Disabled: Story = {
render: () => ({
props: {

View File

@@ -1,4 +1,4 @@
import { Component, HostBinding, input, Input, Optional, Self } from "@angular/core";
import { booleanAttribute, Component, HostBinding, input, Optional, Self } from "@angular/core";
import { NgControl, Validators } from "@angular/forms";
import { BitFormControlAbstraction } from "../form-control";
@@ -11,6 +11,7 @@ let nextId = 0;
providers: [{ provide: BitFormControlAbstraction, useExisting: RadioInputComponent }],
host: {
"[id]": "this.id()",
"[disabled]": "disabled",
},
})
export class RadioInputComponent implements BitFormControlAbstraction {
@@ -74,30 +75,17 @@ export class RadioInputComponent implements BitFormControlAbstraction {
constructor(@Optional() @Self() private ngControl?: NgControl) {}
// TODO: Skipped for signal migration because:
// Accessor inputs cannot be migrated as they are too complex.
@HostBinding()
@Input()
get disabled() {
return this._disabled ?? this.ngControl?.disabled ?? false;
}
set disabled(value: any) {
this._disabled = value != null && value !== false;
}
private _disabled?: boolean;
readonly disabledInput = input(false, { transform: booleanAttribute, alias: "disabled" });
// TODO migrate to computed signal when Angular adds signal support to reactive forms
// https://bitwarden.atlassian.net/browse/CL-819
get disabled() {
return this.disabledInput() || this.ngControl?.disabled || false;
}
// TODO: Skipped for signal migration because:
// Accessor inputs cannot be migrated as they are too complex.
@Input()
get required() {
return (
this._required ?? this.ngControl?.control?.hasValidator(Validators.requiredTrue) ?? false
);
return this.ngControl?.control?.hasValidator(Validators.requiredTrue) ?? false;
}
set required(value: any) {
this._required = value != null && value !== false;
}
private _required?: boolean;
get hasError() {
return !!(this.ngControl?.status === "INVALID" && this.ngControl?.touched);