mirror of
https://github.com/bitwarden/browser
synced 2025-12-15 07:43:35 +00:00
[PM-15847] libs/components strict migration (#15738)
This PR migrates `libs/components` to use strict TypeScript. - Remove `@ts-strict-ignore` from each file in `libs/components` and resolved any new compilation errors - Converted ViewChild and ContentChild decorators to use the new signal-based queries using the [Angular signal queries migration](https://angular.dev/reference/migrations/signal-queries) - Made view/content children `required` where appropriate, eliminating the need for additional null checking. This helped simplify the strict migration. --- Co-authored-by: Vicki League <vleague@bitwarden.com>
This commit is contained in:
@@ -1,5 +1,3 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
import { Component, booleanAttribute, input } from "@angular/core";
|
||||
|
||||
import { MappedOptionComponent } from "./option";
|
||||
|
||||
@@ -1,6 +1,3 @@
|
||||
// FIXME: Update this file to be type safe and remove this and next line
|
||||
// @ts-strict-ignore
|
||||
|
||||
import { hasModifierKey } from "@angular/cdk/keycodes";
|
||||
import {
|
||||
Component,
|
||||
@@ -10,7 +7,6 @@ import {
|
||||
Optional,
|
||||
QueryList,
|
||||
Self,
|
||||
ViewChild,
|
||||
Output,
|
||||
EventEmitter,
|
||||
input,
|
||||
@@ -18,6 +14,7 @@ import {
|
||||
computed,
|
||||
model,
|
||||
signal,
|
||||
viewChild,
|
||||
} from "@angular/core";
|
||||
import {
|
||||
ControlValueAccessor,
|
||||
@@ -47,7 +44,7 @@ let nextId = 0;
|
||||
},
|
||||
})
|
||||
export class SelectComponent<T> implements BitFormFieldControl, ControlValueAccessor {
|
||||
@ViewChild(NgSelectComponent) select: NgSelectComponent;
|
||||
readonly select = viewChild.required(NgSelectComponent);
|
||||
|
||||
/** Optional: Options can be provided using an array input or using `bit-option` */
|
||||
readonly items = model<Option<T>[] | undefined>();
|
||||
@@ -55,13 +52,13 @@ export class SelectComponent<T> implements BitFormFieldControl, ControlValueAcce
|
||||
readonly placeholder = input(this.i18nService.t("selectPlaceholder"));
|
||||
@Output() closed = new EventEmitter();
|
||||
|
||||
protected selectedValue = signal<T>(undefined);
|
||||
selectedOption: Signal<Option<T>> = computed(() =>
|
||||
protected selectedValue = signal<T | undefined | null>(undefined);
|
||||
selectedOption: Signal<Option<T> | null | undefined> = computed(() =>
|
||||
this.findSelectedOption(this.items(), this.selectedValue()),
|
||||
);
|
||||
protected searchInputId = `bit-select-search-input-${nextId++}`;
|
||||
|
||||
private notifyOnChange?: (value: T) => void;
|
||||
private notifyOnChange?: (value?: T | null) => void;
|
||||
private notifyOnTouched?: () => void;
|
||||
|
||||
constructor(
|
||||
@@ -104,7 +101,7 @@ export class SelectComponent<T> implements BitFormFieldControl, ControlValueAcce
|
||||
set disabled(value: any) {
|
||||
this._disabled = value != null && value !== false;
|
||||
}
|
||||
private _disabled: boolean;
|
||||
private _disabled?: boolean;
|
||||
|
||||
/**Implemented as part of NG_VALUE_ACCESSOR */
|
||||
writeValue(obj: T): void {
|
||||
@@ -112,7 +109,7 @@ export class SelectComponent<T> implements BitFormFieldControl, ControlValueAcce
|
||||
}
|
||||
|
||||
/**Implemented as part of NG_VALUE_ACCESSOR */
|
||||
registerOnChange(fn: (value: T) => void): void {
|
||||
registerOnChange(fn: (value?: T | null) => void): void {
|
||||
this.notifyOnChange = fn;
|
||||
}
|
||||
|
||||
@@ -151,11 +148,11 @@ export class SelectComponent<T> implements BitFormFieldControl, ControlValueAcce
|
||||
get ariaDescribedBy() {
|
||||
return this._ariaDescribedBy;
|
||||
}
|
||||
set ariaDescribedBy(value: string) {
|
||||
set ariaDescribedBy(value: string | undefined) {
|
||||
this._ariaDescribedBy = value;
|
||||
this.select?.searchInput.nativeElement.setAttribute("aria-describedby", value);
|
||||
this.select()?.searchInput.nativeElement.setAttribute("aria-describedby", value ?? "");
|
||||
}
|
||||
private _ariaDescribedBy: string;
|
||||
private _ariaDescribedBy?: string;
|
||||
|
||||
/**Implemented as part of BitFormFieldControl */
|
||||
get labelForId() {
|
||||
@@ -176,20 +173,24 @@ export class SelectComponent<T> implements BitFormFieldControl, ControlValueAcce
|
||||
set required(value: any) {
|
||||
this._required = value != null && value !== false;
|
||||
}
|
||||
private _required: boolean;
|
||||
private _required?: boolean;
|
||||
|
||||
/**Implemented as part of BitFormFieldControl */
|
||||
get hasError() {
|
||||
return this.ngControl?.status === "INVALID" && this.ngControl?.touched;
|
||||
return !!(this.ngControl?.status === "INVALID" && this.ngControl?.touched);
|
||||
}
|
||||
|
||||
/**Implemented as part of BitFormFieldControl */
|
||||
get error(): [string, any] {
|
||||
const key = Object.keys(this.ngControl?.errors)[0];
|
||||
return [key, this.ngControl?.errors[key]];
|
||||
const errors = this.ngControl?.errors ?? {};
|
||||
const key = Object.keys(errors)[0];
|
||||
return [key, errors[key]];
|
||||
}
|
||||
|
||||
private findSelectedOption(items: Option<T>[] | undefined, value: T): Option<T> | undefined {
|
||||
private findSelectedOption(
|
||||
items: Option<T>[] | undefined,
|
||||
value: T | null | undefined,
|
||||
): Option<T> | undefined {
|
||||
return items?.find((item) => item.value === value);
|
||||
}
|
||||
|
||||
@@ -207,7 +208,7 @@ export class SelectComponent<T> implements BitFormFieldControl, ControlValueAcce
|
||||
* Needs to be arrow function to retain `this` scope.
|
||||
*/
|
||||
protected onKeyDown = (event: KeyboardEvent) => {
|
||||
if (this.select.isOpen && event.key === "Escape" && !hasModifierKey(event)) {
|
||||
if (this.select().isOpen && event.key === "Escape" && !hasModifierKey(event)) {
|
||||
event.stopPropagation();
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user