diff --git a/libs/ui/checkbox/brain/src/lib/brn-checkbox-ng-model.component.spec.ts b/libs/ui/checkbox/brain/src/lib/brn-checkbox-ng-model.component.spec.ts
index d99a43be5..3dc8a0dcd 100644
--- a/libs/ui/checkbox/brain/src/lib/brn-checkbox-ng-model.component.spec.ts
+++ b/libs/ui/checkbox/brain/src/lib/brn-checkbox-ng-model.component.spec.ts
@@ -1,4 +1,4 @@
-import { Component, Input } from '@angular/core';
+import { Component, input, model } from '@angular/core';
import { FormsModule } from '@angular/forms';
import { BrnCheckboxComponent } from './brn-checkbox.component';
@@ -7,15 +7,14 @@ import { BrnCheckboxComponent } from './brn-checkbox.component';
standalone: true,
template: `
`,
imports: [BrnCheckboxComponent, FormsModule],
})
export class BrnCheckboxNgModelSpecComponent {
- @Input()
- public disabled = false;
- @Input()
- public airplaneMode = false;
+ public readonly disabled = input(false);
+
+ public readonly airplaneMode = model(false);
}
diff --git a/libs/ui/checkbox/brain/src/lib/brn-checkbox-ng-model.spec.ts b/libs/ui/checkbox/brain/src/lib/brn-checkbox-ng-model.spec.ts
index c32ff5f39..b8f3d9e3d 100644
--- a/libs/ui/checkbox/brain/src/lib/brn-checkbox-ng-model.spec.ts
+++ b/libs/ui/checkbox/brain/src/lib/brn-checkbox-ng-model.spec.ts
@@ -24,7 +24,7 @@ describe('BrnCheckboxComponentNgModelIntegration', () => {
expect(labelElement).toBeInTheDocument();
await user.click(labelElement);
await screen.findByDisplayValue('on');
- expect(container.fixture.componentInstance.airplaneMode).toBe(true);
+ expect(container.fixture.componentInstance.airplaneMode()).toBe(true);
});
it('should set input as default correctly and click should toggle then', async () => {
@@ -32,21 +32,21 @@ describe('BrnCheckboxComponentNgModelIntegration', () => {
await user.click(labelElement);
await screen.findByDisplayValue('off');
- expect(container.fixture.componentInstance.airplaneMode).toBe(false);
+ expect(container.fixture.componentInstance.airplaneMode()).toBe(false);
await user.click(labelElement);
await screen.findByDisplayValue('on');
- expect(container.fixture.componentInstance.airplaneMode).toBe(true);
+ expect(container.fixture.componentInstance.airplaneMode()).toBe(true);
});
it('should set input as default correctly and enter should toggle then', async () => {
const { user, container } = await setup(true);
await user.keyboard('[Tab][Enter]');
- expect(container.fixture.componentInstance.airplaneMode).toBe(false);
+ expect(container.fixture.componentInstance.airplaneMode()).toBe(false);
await user.keyboard('[Enter]');
- expect(container.fixture.componentInstance.airplaneMode).toBe(true);
+ expect(container.fixture.componentInstance.airplaneMode()).toBe(true);
});
it('should do nothing when disabled', async () => {
@@ -54,10 +54,10 @@ describe('BrnCheckboxComponentNgModelIntegration', () => {
await user.click(labelElement);
await screen.findByDisplayValue('off');
- expect(container.fixture.componentInstance.airplaneMode).toBe(false);
+ expect(container.fixture.componentInstance.airplaneMode()).toBe(false);
await user.click(labelElement);
await screen.findByDisplayValue('off');
- expect(container.fixture.componentInstance.airplaneMode).toBe(false);
+ expect(container.fixture.componentInstance.airplaneMode()).toBe(false);
});
});
diff --git a/libs/ui/checkbox/brain/src/lib/brn-checkbox.component.ts b/libs/ui/checkbox/brain/src/lib/brn-checkbox.component.ts
index b06f47456..eb0fe23a5 100644
--- a/libs/ui/checkbox/brain/src/lib/brn-checkbox.component.ts
+++ b/libs/ui/checkbox/brain/src/lib/brn-checkbox.component.ts
@@ -5,13 +5,10 @@ import {
ChangeDetectionStrategy,
Component,
ElementRef,
- EventEmitter,
HostListener,
type OnDestroy,
- Output,
PLATFORM_ID,
Renderer2,
- ViewChild,
ViewEncapsulation,
booleanAttribute,
computed,
@@ -20,7 +17,9 @@ import {
inject,
input,
model,
+ output,
signal,
+ viewChild,
} from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { ChangeFn, TouchFn } from '@spartan-ng/ui-forms-brain';
@@ -73,11 +72,11 @@ const CONTAINER_POST_FIX = '-checkbox';
`,
host: {
- '[attr.tabindex]': '_disabled() ? "-1" : "0"',
+ '[attr.tabindex]': 'state().disabled() ? "-1" : "0"',
'[attr.data-state]': '_dataState()',
'[attr.data-focus-visible]': 'focusVisible()',
'[attr.data-focus]': 'focused()',
- '[attr.data-disabled]': '_disabled()',
+ '[attr.data-disabled]': 'state().disabled()',
'[attr.aria-labelledby]': 'null',
'[attr.aria-label]': 'null',
'[attr.aria-describedby]': 'null',
@@ -136,20 +135,20 @@ export class BrnCheckboxComponent implements AfterContentInit, OnDestroy {
public readonly required = input(false, { transform: booleanAttribute });
- private readonly _disabled = signal(false);
- /** Only used as input */
public readonly disabled = input(false, { transform: booleanAttribute });
+ protected readonly state = computed(() => ({
+ disabled: signal(this.disabled()),
+ }));
+
// eslint-disable-next-line @typescript-eslint/no-empty-function
protected _onChange: ChangeFn = () => {};
// eslint-disable-next-line @typescript-eslint/no-empty-function
private _onTouched: TouchFn = () => {};
- @ViewChild('checkBox', { static: true })
- public checkbox?: ElementRef;
+ public readonly checkbox = viewChild.required>('checkBox');
- @Output()
- public readonly changed = new EventEmitter();
+ public readonly changed = output();
constructor() {
effect(() => {
@@ -157,30 +156,22 @@ export class BrnCheckboxComponent implements AfterContentInit, OnDestroy {
if (!parent) return;
// check if parent is a label and assume it is for this checkbox
if (parent?.tagName === 'LABEL') {
- this._renderer.setAttribute(parent, 'data-disabled', this._disabled() ? 'true' : 'false');
+ this._renderer.setAttribute(parent, 'data-disabled', this.state().disabled() ? 'true' : 'false');
return;
}
if (!this._isBrowser) return;
const label = parent?.querySelector(`label[for="${this.id()}"]`);
if (!label) return;
- this._renderer.setAttribute(label, 'data-disabled', this._disabled() ? 'true' : 'false');
+ this._renderer.setAttribute(label, 'data-disabled', this.state().disabled() ? 'true' : 'false');
});
-
- effect(
- () => {
- // sync disabled input
- this._disabled.set(this.disabled());
- },
- { allowSignalWrites: true },
- );
}
@HostListener('click', ['$event'])
@HostListener('keyup.space', ['$event'])
@HostListener('keyup.enter', ['$event'])
toggle(event: Event) {
- if (this._disabled()) return;
+ if (this.state().disabled()) return;
event.preventDefault();
const previousChecked = this.checked();
this.checked.set(previousChecked === 'indeterminate' ? true : !previousChecked);
@@ -208,15 +199,13 @@ export class BrnCheckboxComponent implements AfterContentInit, OnDestroy {
}
});
- if (!this.checkbox) return;
-
- this.checkbox.nativeElement.indeterminate = this.checked() === 'indeterminate';
- if (this.checkbox.nativeElement.indeterminate) {
- this.checkbox.nativeElement.value = 'indeterminate';
+ this.checkbox().nativeElement.indeterminate = this.checked() === 'indeterminate';
+ if (this.checkbox().nativeElement.indeterminate) {
+ this.checkbox().nativeElement.value = 'indeterminate';
} else {
- this.checkbox.nativeElement.value = this.checked() ? 'on' : 'off';
+ this.checkbox().nativeElement.value = this.checked() ? 'on' : 'off';
}
- this.checkbox.nativeElement.dispatchEvent(new Event('change'));
+ this.checkbox().nativeElement.dispatchEvent(new Event('change'));
}
ngOnDestroy() {
@@ -241,7 +230,7 @@ export class BrnCheckboxComponent implements AfterContentInit, OnDestroy {
/** Implemented as a part of ControlValueAccessor. */
setDisabledState(isDisabled: boolean): void {
- this._disabled.set(isDisabled);
+ this.state().disabled.set(isDisabled);
}
/**
diff --git a/libs/ui/checkbox/helm/src/lib/hlm-checkbox.component.ts b/libs/ui/checkbox/helm/src/lib/hlm-checkbox.component.ts
index 32a8d66c3..6cb73dac4 100644
--- a/libs/ui/checkbox/helm/src/lib/hlm-checkbox.component.ts
+++ b/libs/ui/checkbox/helm/src/lib/hlm-checkbox.component.ts
@@ -1,15 +1,4 @@
-import {
- Component,
- EventEmitter,
- Output,
- booleanAttribute,
- computed,
- effect,
- forwardRef,
- input,
- model,
- signal,
-} from '@angular/core';
+import { Component, booleanAttribute, computed, forwardRef, input, model, output, signal } from '@angular/core';
import { NG_VALUE_ACCESSOR } from '@angular/forms';
import { BrnCheckboxComponent } from '@spartan-ng/ui-checkbox-brain';
import { hlm } from '@spartan-ng/ui-core';
@@ -32,7 +21,7 @@ export const HLM_CHECKBOX_VALUE_ACCESSOR = {
[name]="name()"
[class]="_computedClass()"
[checked]="checked()"
- [disabled]="_disabled()"
+ [disabled]="state().disabled()"
[required]="required()"
[aria-label]="ariaLabel()"
[aria-labelledby]="ariaLabelledby()"
@@ -59,7 +48,7 @@ export class HlmCheckboxComponent {
'group inline-flex border border-foreground shrink-0 cursor-pointer items-center rounded-sm focus-visible:outline-none focus-visible:ring-2 focus-visible:ring-ring' +
' focus-visible:ring-offset-2 focus-visible:ring-offset-background data-[state=checked]:text-background data-[state=checked]:bg-primary data-[state=unchecked]:bg-background',
this.userClass(),
- this._disabled() ? 'cursor-not-allowed opacity-50' : '',
+ this.state().disabled() ? 'cursor-not-allowed opacity-50' : '',
),
);
@@ -80,25 +69,20 @@ export class HlmCheckboxComponent {
public readonly name = input(null);
public readonly required = input(false, { transform: booleanAttribute });
- protected readonly _disabled = signal(false);
public readonly disabled = input(false, { transform: booleanAttribute });
- private disableInput = effect(
- () => {
- this._disabled.set(this.disabled());
- },
- { allowSignalWrites: true },
- );
+ protected readonly state = computed(() => ({
+ disabled: signal(this.disabled()),
+ }));
// icon inputs
public readonly checkIconName = input('lucideCheck');
- public readonly checkIconClass = input('');
+ public readonly checkIconClass = input('');
- @Output()
- public changed = new EventEmitter();
+ public readonly changed = output();
protected _handleChange(): void {
- if (this._disabled()) return;
+ if (this.state().disabled()) return;
const previousChecked = this.checked();
this.checked.set(previousChecked === 'indeterminate' ? true : !previousChecked);
@@ -128,6 +112,6 @@ export class HlmCheckboxComponent {
}
setDisabledState(isDisabled: boolean): void {
- this._disabled.set(isDisabled);
+ this.state().disabled.set(isDisabled);
}
}