0

I'm trying to create an Angular Elements component to embed in a hosted web page, and I want my component to contain an Angular reactive form.

Build fails with error: "Can't bind to 'formGroup' since it isn't a known property of 'form'."

Can anyone identify what I'm doing wrong?

Edit: This is Angular 9 and TypeScript 3.7 running on the latest version of the Angular CLI. Stackblitz: https://stackblitz.com/edit/angular-57wq1s

Edit 2: The updated Stackblitz code no longer throws a compile-time error, but the control does not finish rendering. The Submit button does not render. If I remove the 'formControlName' directive from the password input, the component does render completely.

Edit 3: StackBlitz seems to be working now, but if I download to my computer, npm install and ng serve, I get the problem where it renders the textbox but not the button.

Index.html

<!doctype html>
<html lang="en">
<body>
  <app-password-reset></app-password-reset>
</body>
</html>

app.module.ts

@NgModule({
  declarations: [],
  imports: [
    BrowserModule,
    FormsModule,
    ReactiveFormsModule
  ],
  entryComponents: [PasswordResetComponent],
  providers: [],
})
export class AppModule {
  constructor(injector: Injector) {
    const passwordResetElement = createCustomElement(PasswordResetComponent, {injector});
    customElements.define('app-password-reset', passwordResetElement);
  }

  ngDoBootstrap(): void { }
}

password-reset.component.ts

@Component({
  template: `
    <form [formGroup]="resetForm" (ngSubmit)="formSubmit($event)">
      <input type="password" formControlName="password">
      <button type="submit">Reset Password</button>
    </form>`
})
export class PasswordResetComponent {

  constructor(private fb: FormBuilder) { }

  resetForm = this.fb.group({
    password: [null, Validators.required],
  });

  formSubmit(event: Event) {
    alert('it works');
  }

}
Chad
  • 21
  • 6
  • I think you also need to import FormsModule – Barkha Feb 19 '20 at 14:01
  • OK, I added that to my app.module.ts, and I'm still getting the same error. I'll update my original code sample. – Chad Feb 19 '20 at 16:50
  • can you create this project in https://stackblitz.com/ ? – Sats Feb 19 '20 at 17:15
  • I got it into Stackblitz, but I'm not sure if it's compatible with Angular Elements. It's giving me a different error... https://stackblitz.com/edit/angular-fsyral – Chad Feb 19 '20 at 18:32
  • @SatishPai -- forgot to tag you – Chad Feb 19 '20 at 18:55
  • @Chad now the current error we are getting is different from what was mentioned in the question. Do you want to create the component dynamically ? – Sats Feb 20 '20 at 05:11
  • @SatishPai -- OK, my mistake. I've updated a package and fixed the secondary problem. If you go back to the StackBlitz, you should now see that it only partially loads the control. The sumbit button is missing. This is not the original error, but it's a symptom of the same problem. – Chad Feb 20 '20 at 17:08
  • @Chad i am getting this error `TypeError: Failed to construct 'HTMLElement': Please use the 'new' operator, this DOM object constructor cannot be called as a function` from your shared stackblitz. Have you saved the changes after the changes in package file ? – Sats Feb 20 '20 at 17:30
  • @SatishPai -- The fix for that was to pin the version of document-register-element to version 1.8.1. I've just saved it. Should be working now. It appears that the whole component is now working for me in StackBlitz, but if I download to my local computer, run npm install and ng serve, I'm getting the problem where the text box renders but the button doesn't. – Chad Feb 20 '20 at 17:42
  • @Chad checking now there is no error. – Sats Feb 20 '20 at 17:43
  • @Chad what version of chrome you are using ? – Sats Feb 20 '20 at 17:46
  • @SatishPai -- 79.0.3945.130 – Chad Feb 20 '20 at 18:27
  • @SatishPai -- Very strange. I'm getting weird variations on this problem depending on the project and environment. In my real application where I'm trying to solve the problem, the custom element doesn't render at all, like you are seeing. Sometimes when I run the example in StackBlitz it works, especially when I fork the project into a new one. Sometimes it doesn't. When I download the project from StackBlitz and run locally, I can see the textbox inside the component render, but not the sumbit button. Other times I get the error in my original post. – Chad Feb 20 '20 at 18:41
  • @Chad agree i am able to reproduce the same issue now. TextBox is render but not the button, need to check it – Sats Feb 20 '20 at 19:22
  • @SatishPai -- Looks like this could be an issue with Ivy. Here's a StackBlitz using the Angular CLI v. 9 with Ivy: https://stackblitz.com/edit/angular-57wq1s and here's one on CLI 8 without Ivy: https://stackblitz.com/edit/angular-cqvkzw Non-Ivy works for me while Ivy doesn't. Are you seeing the same? – Chad Feb 20 '20 at 19:53
  • @Chad I agree with you. I am trying a way were ivy will work with custom element – Sats Feb 21 '20 at 05:27

1 Answers1

1

First Import FormsModule in your app.module.ts

You can use FormBuilder to build your form and set the password using Validators. It's easy to use and facilitate working.

Here's how I do it.

Html Page

<form [formGroup]='addEventForm' (ngSubmit)='addEvent(addEventForm.value)'>
</form>

Component.ts

import { FormGroup, FormBuilder, Validators } from '@angular/forms';

addEventForm: FormGroup;
  constructor(formBuilder: FormBuilder) {
this.addEventForm = formBuilder.group({
  title: [null, Validators.required],
  location: [null, Validators.required],
  description: [null, Validators.required],
  startDateValue: [null, Validators.required],
  endDateValue: [null, Validators.required],
  startTime: [null, Validators.required],
  endTime: [null, Validators.required],
  eventType: ['payed'],
  price: ''
});
}

Please note that you need to import FormBuilder.

Hope that helps you a little bit.

Mohamad Mousheimish
  • 1,641
  • 3
  • 16
  • 48