Skip to content

Instantly share code, notes, and snippets.

@wfairclough
Last active November 21, 2023 17:18
Show Gist options
  • Save wfairclough/b5752ac935a6c54e674f4d61418d0ee3 to your computer and use it in GitHub Desktop.
Save wfairclough/b5752ac935a6c54e674f4d61418d0ee3 to your computer and use it in GitHub Desktop.
ControlValueAccessors for Shoelace Custom Elements
import { Directive, forwardRef, NgModule, ElementRef, Renderer2 } from '@angular/core';
import {
CheckboxControlValueAccessor,
DefaultValueAccessor,
FormsModule,
NG_VALUE_ACCESSOR,
RadioControlValueAccessor,
ReactiveFormsModule,
SelectControlValueAccessor,
SelectMultipleControlValueAccessor,
} from '@angular/forms';
@Directive({
selector: 'sl-input[formControlName],sl-input[formControl],sl-input[ngModel]',
host: {
'(sl-input)': '$any(this)._handleInput($event.target.value)',
'(sl-blur)': 'onTouched()',
'(sl-change)': '$any(this)._compositionEnd($event.target.value)',
},
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SlInputControl), multi: true }],
})
export class SlInputControl extends DefaultValueAccessor { }
@Directive({
selector: 'sl-checkbox[formControlName],sl-checkbox[formControl],sl-checkbox[ngModel]',
host: {'(sl-change)': 'onChange($event.target.checked)', '(sl-blur)': 'onTouched()'},
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SlCheckboxControl),multi: true }],
})
export class SlCheckboxControl extends CheckboxControlValueAccessor { }
@Directive({
selector: 'sl-radio[formControlName],sl-radio[formControl],sl-radio[ngModel]]',
host: {'(sl-blur)': 'onTouched()'},
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SlRadioControl), multi: true }],
})
export class SlRadioControl extends RadioControlValueAccessor { }
@Directive({
selector: 'sl-radio-group[formControlName],sl-radio-group[formControl],sl-radio-group[ngModel]]',
host: {
'(sl-input)': '$any(this)._handleInput($event.target.value)',
'(sl-blur)': 'onTouched()',
},
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SlRadioGroupControl), multi: true }],
})
export class SlRadioGroupControl extends DefaultValueAccessor { }
@Directive({
selector: 'sl-select:not([multiple])[formControlName],sl-select:not([multiple])[formControl],sl-select:not([multiple])[ngModel]',
host: {'(sl-change)': 'onChange($event.target.value)', '(sl-blur)': 'onTouched()'},
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SlSelectControl), multi: true }],
})
export class SlSelectControl extends SelectControlValueAccessor { }
@Directive({
selector: 'sl-select[multiple][formControlName],sl-select[multiple][formControl],sl-select[multiple][ngModel]',
host: {'(sl-change)': 'onChange($event.target)', '(sl-blur)': 'onTouched()'},
providers: [{ provide: NG_VALUE_ACCESSOR, useExisting: forwardRef(() => SlSelectMultipleControl), multi: true }],
})
export class SlSelectMultipleControl extends SelectMultipleControlValueAccessor {
private _elRef: ElementRef;
constructor(_renderer: Renderer2, _elementRef: ElementRef) {
super(_renderer, _elementRef);
this._elRef = _elementRef;
}
override writeValue(value: any): void {
super.writeValue(value);
this._elRef.nativeElement.value = this.value;
}
}
@NgModule({
imports: [FormsModule, ReactiveFormsModule],
declarations: [SlInputControl, SlCheckboxControl, SlRadioControl, SlRadioGroupControl, SlSelectControl, SlSelectMultipleControl],
exports: [SlInputControl, SlCheckboxControl, SlRadioControl, SlRadioGroupControl, SlSelectControl, SlSelectMultipleControl],
})
export class SlValueAccessorsModule {}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment