Skip to content

Instantly share code, notes, and snippets.

@zecka
Created September 30, 2025 12:36
Show Gist options
  • Save zecka/6a239390532009e2a3435c3f75770c23 to your computer and use it in GitHub Desktop.
Save zecka/6a239390532009e2a3435c3f75770c23 to your computer and use it in GitHub Desktop.
radio group angular
// radio-group.component
import { Component, ContentChildren, QueryList, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';
import { RadioItemComponent } from './radio-item.component';
let nextId = 0;
@Component({
selector: 'radio-group',
template: `<ng-content></ng-content>`,
providers: [
{
provide: NG_VALUE_ACCESSOR,
useExisting: forwardRef(() => RadioGroupComponent),
multi: true,
},
],
})
export class RadioGroupComponent implements ControlValueAccessor {
private _value: any;
name = `radio-group-${nextId++}`;
// ✅ récupère aussi les descendants (pas seulement les enfants directs)
@ContentChildren(RadioItemComponent, { descendants: true })
items!: QueryList<RadioItemComponent>;
private onChange: (value: any) => void = () => {};
private onTouched: () => void = () => {};
set value(val: any) {
this._value = val;
this.updateItems();
this.onChange(val);
this.onTouched();
}
get value() {
return this._value;
}
writeValue(obj: any): void {
this._value = obj;
this.updateItems();
}
registerOnChange(fn: any): void {
this.onChange = fn;
}
registerOnTouched(fn: any): void {
this.onTouched = fn;
}
setDisabledState?(isDisabled: boolean): void {
this.items.forEach(item => item.disabled.set(isDisabled));
}
select(value: any) {
this.value = value;
}
private updateItems() {
if (!this.items) return;
this.items.forEach(item => {
item.checked.set(item.value() === this._value);
item.name.set(this.name);
});
}
}
//radio-item.component
import { Component, Optional, signal, input } from '@angular/core';
import { RadioGroupComponent } from './radio-group.component';
@Component({
selector: 'radio-item',
template: `
<label>
<input
type="radio"
[name]="name()"
[value]="value()"
[checked]="checked()"
[disabled]="disabled()"
(change)="onChange()"
/>
<ng-content></ng-content>
</label>
`,
})
export class RadioItemComponent {
value = input<any>();
name = signal<string>('');
checked = signal(false);
disabled = signal(false);
constructor(@Optional() private group: RadioGroupComponent) {}
onChange() {
if (this.disabled()) return;
this.group?.select(this.value());
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment