0

I created a lit-element web component that contains an <input type="text">. Actually I just extended LionInput.

import { InputMixin } from '@core/mixin/form/InputMixin';
import { customElement} from '@lion/core';
import { LionInput } from '@lion/input';

@customElement('ds-input')
export class DSInput extends InputMixin(LionInput) {}

Inside app.module of my Angular app I added the schemas property:

schemas: [CUSTOM_ELEMENTS_SCHEMA],

As you can see in the image below, <my-input> is recognised as web component inside my angular reative form enter image description here

The problem is when I try to reach the <input> inside my web component doing this:

<form [formGroup]="myForm">
   <ds-input [formControlName]="'name'"></ds-input> 
</form>


this.myForm = new FormGroup({
  name: new FormControl()
});

I get the error:

 'ERROR Error: No value accessor for form control with name: 'name'

I perfectly understand the reason of the error, but I can't understand how to solve it, how to make Angular reach the <input> inside <ds-input> I don't find much documentation about how to integrate litElement web component inside an Angular app.

Matt
  • 265
  • 4
  • 17

2 Answers2

0

Error said you don't have any control for the control named "name". So you can try to do it like this

Try this is your html

<form [formGroup]="myForm">
   <ds-input [formControl]="name"></ds-input> 
</form>

And in your typescript:

public formGroup : FormGroup;
public nameFC : FormControl = new FormControl();

this.formGroup = new FormGroup({
    name: this.nameFC
})
  • Hi, thank you for you answer; but that's not the problem. I already created a formGroup in my component, even I didn't add the code in this post. Anyway now I added also the code of the angular component The problem is that angular can't reach the input field inside the component ds-input – Matt Jul 07 '22 at 19:21
0

Your component probably needs to implement a ControlValueAccessor interface to create a custom form control directive that integrates with Angular forms.

Something like this:

import { Directive, ElementRef, HostListener, Provider, forwardRef } from '@angular/core';
import { ControlValueAccessor, NG_VALUE_ACCESSOR } from '@angular/forms';

export const INPUT_VALUE_ACCESSOR: Provider = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => DsInputDirective),
  multi: true
};

@Directive({
  selector: 'ds-input',
  providers: [INPUT_VALUE_ACCESSOR]
})
export class DsInputDirective implements ControlValueAccessor {
  private _val: any;
  onChange: any = () => {};
  onTouched: any = () => {};

  get value() {
    return this._val;
  }

  set value(value: any) {
    if (!value || value === this._val) return;
    this._val = value;

    this.onChange(this._val);
    this.onTouched();
  }

  constructor(private elRef: ElementRef) {}

  writeValue(value: any): void {
    this.elRef.nativeElement.modelValue = value;
    this.value = value;
  }

  registerOnChange(fn: any): void {
    this.onChange = fn;
  }

  registerOnTouched(fn: any): void {
    this.onTouched = fn;
  }

  @HostListener('model-value-changed', ['$event.detail'])
  listenForValueChange(detail: any) {
    if (detail.isTriggeredByUser) {
      this.value = this.elRef.nativeElement.modelValue;
    }
  }

  @HostListener('blur')
  listenForControlBlur() {
    this.onTouched();
  }
}