0

I've being trying to create custom elements with angular elements and for form inputs I've being trying to use angular's ControlValueAccessor for that as discussed in this article by Eliran Eliassy.

But when I follow the guide, and completed the code - I ran into this problem. No provider for NgControl. I have already imported FormsModule and ReactiveFormsModule to app.module.ts file which is the remedy for this error (as normal). But it haven't fixed this time.

StackBlitz Example

What will be the problem? I attached the stackbliz above for your reference.

6 Answers 6

3

Thanks for posting here for more people get benefited from it.

You did 2 mistakes there:

  1. When you injecting the NgControl, you don't have to provide the NG_VALUE_ACCESSOR token. the reason is NgControl is already providing the NG_VALUE_ACCESSOR token, and if you do it as well, you will run into a circular dependency issue.

  2. Because your TestComponent is an entry component, you also have to add the @Optional() decorator before your NgControl injection. The reason is when you declaring a component in the entry component, angular compiles it factory even that it's not on the template, and because it's not part of any form and doesn't have any From directive on it, you will get this error of No provider for NgControl

Hope that helps!

Sign up to request clarification or add additional context in comments.

9 Comments

Hello @Eliran, i tried them actually. Check the updated StackBlitz with the recommendations you mentioned. Now the previous error is gone, but introduced these two new ones. ``` Error: No value accessor for form control with name: 'email' ``` And ``` TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function. ``` You can recreate them in the updated StackBlitz. Thank you :)
Plus, when i'm trying your solution in my local environment - it gives the error -> ERROR TypeError: Cannot set property 'valueAccessor' of null and ERROR Error: Uncaught (in promise): Error: No value accessor for form control with name: 'email'
Again, because not always your DI will get NgControl, of course, you can just add if statement to check wheater you got it or not before you set the valueAccessor prop.
I tried that even @Eliran :/. That leads to ERROR TypeError: Cannot read property 'control' of null which is actually the expected behaviour. So how can we rightfully inject the DI for NgControl if the one coming from the DI is null?
I see...and it makes sense if we thinking about it again. So, I think that for that case, maybe getting the NgControl from the DI is not the best option. Need to find another way of doing it.
|
1

Something is wrong with your AppModule and DoBootstrap implementation. If you remove it and additionally remove your component from entryComponents in appModule and change how it is used at the app-component.html everything seems to work fine.

app.module.ts

@NgModule({
  imports: [BrowserModule, FormsModule, ReactiveFormsModule],
  declarations: [AppComponent, HelloComponent, TestInputComponent],
  bootstrap: [AppComponent],
  schemas: [CUSTOM_ELEMENTS_SCHEMA]
})
export class AppModule  {
  constructor(private injector: Injector) {

  }
}

app.component.html

<form class="form-signin" (ngSubmit)="onSubmit(f.value)" #f="ngForm" >
  <app-test-input [placeholder]="'Email'"
                          [isRequired]="true"
                          [errorMsg]="'Please enter your name'"
                          [label] = "'User Email'"
                          [pattern]="'[A-Za-z0-9._%-]+@[A-Za-z0-9._%-]+\\.[a-z]{2,3}'"
                          ngModel name="email"></app-test-input>

  <button class="btn btn-lg btn-primary btn-block" [disabled]="!f.valid" type="submit">Sign in</button>
</form>

3 Comments

No :/. That didn't fixed the issue. On the other hand, we shouldn't add NG_VALUE_ACCESSOR provider since NgControl already importing that (which may lead to cyclic dependency)
I have to use doBootstrap for creating the custom element from angular elements anyhow :/
Even in that example they have placed the custom-element-comp (testcomponent) in the entry components list (not in the declarations array). What to do about that?
1

Found the solution.

Fixed the error by adding the ngDefaultControl as a directive in the custom element and implementing the part of the ControlValueAccessor manually.

Here is an example of implementation (Don't mind the validation part, not finished yet) StackBlitz

Please follow these issues for more information.

Comments

1

Provide NgControl in your TestingModule like so:

  beforeEach(() => {
    TestBed.configureTestingModule({
      imports: [ ... ReactiveFormsModule, FormsModule ... ],
      declarations: [
        ...Component,
      ],
      providers: [NgControl], // <-- this
    });
    fixture = TestBed.createComponent(...Component);
    component = fixture.componentInstance;
    fixture.detectChanges();
  });

Comments

0

remove this line from your app.module.ts

entryComponents: [TestInputComponent]

also u have removed DoBootstrap implementation from app.module.ts and replace ust-input with app-test-input and it will works.also remove

providers: [
    {
      provide: NG_VALUE_ACCESSOR,
      useExisting: TestInputComponent,
      multi: true
    }]

because it's create cyclic dependency.

Comments

0

For everyone else who get this Error, in my case the problem was a missing formControlName property and a missing formGroup as a parent. If you use custom form controls in your project as well, ensure all references - formControlName's and [formGroup]="myFormGroup" - are set properly.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.