Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ORIGINAL EXCEPTION: No provider for FormGroup

I have a simple form that is suppose to display error messages

errorm-messages.component

import { Component, OnInit, Input } from '@angular/core'
import { NgIf } from '@angular/common'
import {REACTIVE_FORM_DIRECTIVES, FormGroup } from '@angular/forms'

@Component(
    {
      moduleId: module.id,
      selector: 'epimss-error-messages',
      template: `
   <span class="error" *ngIf="errorMessage !== null">{{errorMessage}}</span>`,
      styles: [],
      directives: [REACTIVE_FORM_DIRECTIVES, NgIf]

    })
export class ErrorMessagesComponent implements OnInit {
  @Input()
  ctrlName: string

  constructor(private _form: FormGroup) {
  }

  ngOnInit() {
      }

  get errorMessage() {
    // Find the control in the Host (Parent) form
    let ctrl = this._form.find(this.ctrlName);

    console.log('ctrl| ', ctrl)

//    for (let propertyName of ctrl.errors) {
//      // If control has a error
//      if (ctrl.errors.hasOwnProperty(propertyName) && ctrl.touched) {
//        // Return the appropriate error message from the Validation Service
//        return CustomValidators.getValidatorErrorMessage(propertyName);
//      }
//    }

    return null;
  }

}

Usage

language.component.html after import as a directive in language.component.ts

<div layout = "column"
     layout-align = "start start">
  <md-input required
            placeholder = "First"
            formControlName = "first"></md-input>
  <epimss-error-messages ctrlName = "first"></epimss-error-messages>
  <md-input placeholder = "Second"
            formControlName = "second"></md-input>
  <!--<epimss-error-messages ctrlName = "second"></epimss-error-messages>-->

</div>

Once the line

<epimss-error-messages ctrlName = "first"></epimss-error-messages>

is present I get the following console error and the UI fails to display:

EXCEPTION: Error in http://localhost:4200/app/registration/language/language.component.html:44:2 browser_adapter.ts:74 EXCEPTION: Error in http://localhost:4200/app/registration/language/language.component.html:44:2BrowserDomAdapter.logError @ browser_adapter.ts:74BrowserDomAdapter.logGroup @ browser_adapter.ts:85ExceptionHandler.call @ exception_handler.ts:50(anonymous function) @ application_ref.ts:396ZoneDelegate.invoke @ zone.js:323onInvoke @ ng_zone_impl.ts:64ZoneDelegate.invoke @ zone.js:322Zone.run @ zone.js:216NgZoneImpl.runInner @ ng_zone_impl.ts:96NgZone.run @ ng_zone.ts:211ApplicationRef_.run @ application_ref.ts:384ApplicationRef_.bootstrap @ application_ref.ts:408(anonymous function) @ application_ref.ts:150ZoneDelegate.invoke @ zone.js:323onInvoke @ ng_zone_impl.ts:64ZoneDelegate.invoke @ zone.js:322Zone.run @ zone.js:216(anonymous function) @ zone.js:571ZoneDelegate.invokeTask @ zone.js:356onInvokeTask @ ng_zone_impl.ts:53ZoneDelegate.invokeTask @ zone.js:355Zone.runTask @ zone.js:256drainMicroTaskQueue @ zone.js:474ZoneTask.invoke @ zone.js:426 browser_adapter.ts:74 ORIGINAL EXCEPTION: No provider for FormGroup!BrowserDomAdapter.logError @ browser_adapter.ts:74ExceptionHandler.call @ exception_handler.ts:62(anonymous function) @ application_ref.ts:396ZoneDelegate.invoke @ zone.js:323onInvoke @ ng_zone_impl.ts:64ZoneDelegate.invoke @ zone.js:322Zone.run @ zone.js:216NgZoneImpl.runInner @ ng_zone_impl.ts:96NgZone.run @ ng_zone.ts:211ApplicationRef_.run @ application_ref.ts:384ApplicationRef_.bootstrap @ application_ref.ts:408(anonymous function) @ application_ref.ts:150ZoneDelegate.invoke @ zone.js:323onInvoke @ ng_zone_impl.ts:64ZoneDelegate.invoke @ zone.js:322Zone.run @ zone.js:216(anonymous function) @ zone.js:571ZoneDelegate.invokeTask @ zone.js:356onInvokeTask @ ng_zone_impl.ts:53ZoneDelegate.invokeTask @ zone.js:355Zone.runTask @ zone.js:256drainMicroTaskQueue @ zone.js:474ZoneTask.invoke @ zone.js:426 browser_adapter.ts:74 ORIGINAL STACKTRACE:BrowserDomAdapter.logError @ browser_adapter.ts:74ExceptionHandler.call @ exception_handler.ts:66(anonymous function) @ application_ref.ts:396ZoneDelegate.invoke @ zone.js:323onInvoke @ ng_zone_impl.ts:64ZoneDelegate.invoke @ zone.js:322Zone.run @ zone.js:216NgZoneImpl.runInner @ ng_zone_impl.ts:96NgZone.run @ ng_zone.ts:211ApplicationRef_.run @ application_ref.ts:384ApplicationRef_.bootstrap @ application_ref.ts:408(anonymous function) @ application_ref.ts:150ZoneDelegate.invoke @ zone.js:323onInvoke @ ng_zone_impl.ts:64ZoneDelegate.invoke @ zone.js:322Zone.run @ zone.js:216(anonymous function) @ zone.js:571ZoneDelegate.invokeTask @ zone.js:356onInvokeTask @ ng_zone_impl.ts:53ZoneDelegate.invokeTask @ zone.js:355Zone.runTask @ zone.js:256drainMicroTaskQueue @ zone.js:474ZoneTask.invoke @ zone.js:426 browser_adapter.ts:74 Error: DI Exception at NoProviderError.BaseException [as constructor] (exceptions.ts:13) at NoProviderError.AbstractProviderError [as constructor] (reflective_exceptions.ts:51) at new NoProviderError (reflective_exceptions.ts:84) at ReflectiveInjector_._throwOrNull (reflective_injector.ts:839) at ReflectiveInjector_._getByKeyDefault (reflective_injector.ts:868) at ReflectiveInjector_._getByKey (reflective_injector.ts:830) at ReflectiveInjector_.get (reflective_injector.ts:623) at ElementInjector.get (element_injector.ts:15) at ElementInjector.get (element_injector.ts:15) at _View_LanguageComponent0.createInternal (LanguageComponent.template.js:217)BrowserDomAdapter.logError @ browser_adapter.ts:74ExceptionHandler.call @ exception_handler.ts:67(anonymous function) @ application_ref.ts:396ZoneDelegate.invoke @ zone.js:323onInvoke @ ng_zone_impl.ts:64ZoneDelegate.invoke @ zone.js:322Zone.run @ zone.js:216NgZoneImpl.runInner @ ng_zone_impl.ts:96NgZone.run @ ng_zone.ts:211ApplicationRef_.run @ application_ref.ts:384ApplicationRef_.bootstrap @ application_ref.ts:408(anonymous function) @ application_ref.ts:150ZoneDelegate.invoke @ zone.js:323onInvoke @ ng_zone_impl.ts:64ZoneDelegate.invoke @ zone.js:322Zone.run @ zone.js:216(anonymous function) @ zone.js:571ZoneDelegate.invokeTask @ zone.js:356onInvokeTask @ ng_zone_impl.ts:53ZoneDelegate.invokeTask @ zone.js:355Zone.runTask @ zone.js:256drainMicroTaskQueue @ zone.js:474ZoneTask.invoke @ zone.js:426 browser_adapter.ts:74 ERROR CONTEXT:BrowserDomAdapter.logError @ browser_adapter.ts:74ExceptionHandler.call @ exception_handler.ts:71(anonymous function) @ application_ref.ts:396ZoneDelegate.invoke @ zone.js:323onInvoke @ ng_zone_impl.ts:64ZoneDelegate.invoke @ zone.js:322Zone.run @ zone.js:216NgZoneImpl.runInner @ ng_zone_impl.ts:96NgZone.run @ ng_zone.ts:211ApplicationRef_.run @ application_ref.ts:384ApplicationRef_.bootstrap @ application_ref.ts:408(anonymous function) @ application_ref.ts:150ZoneDelegate.invoke @ zone.js:323onInvoke @ ng_zone_impl.ts:64ZoneDelegate.invoke @ zone.js:322Zone.run @ zone.js:216(anonymous function) @ zone.js:571ZoneDelegate.invokeTask @ zone.js:356onInvokeTask @ ng_zone_impl.ts:53ZoneDelegate.invokeTask @ zone.js:355Zone.runTask @ zone.js:256drainMicroTaskQueue @ zone.js:474ZoneTask.invoke @ zone.js:426 browser_adapter.ts:74 DebugContext {_view: _View_LanguageComponent0, _nodeIndex: 30, _tplRow: 44, _tplCol: 2}BrowserDomAdapter.logError @ browser_adapter.ts:74ExceptionHandler.call @ exception_handler.ts:72(anonymous function) @ application_ref.ts:396ZoneDelegate.invoke @ zone.js:323onInvoke @ ng_zone_impl.ts:64ZoneDelegate.invoke @ zone.js:322Zone.run @ zone.js:216NgZoneImpl.runInner @ ng_zone_impl.ts:96NgZone.run @ ng_zone.ts:211ApplicationRef_.run @ application_ref.ts:384ApplicationRef_.bootstrap @ application_ref.ts:408(anonymous function) @ application_ref.ts:150ZoneDelegate.invoke @ zone.js:323onInvoke @ ng_zone_impl.ts:64ZoneDelegate.invoke @ zone.js:322Zone.run @ zone.js:216(anonymous function) @ zone.js:571ZoneDelegate.invokeTask @ zone.js:356onInvokeTask @ ng_zone_impl.ts:53ZoneDelegate.invokeTask @ zone.js:355Zone.runTask @ zone.js:256drainMicroTaskQueue @ zone.js:474ZoneTask.invoke @ zone.js:426 browser_adapter.ts:84 EXCEPTION: Error in http://localhost:4200/app/registration/language/language.component.html:44:2 ...

Removing the last code above and the display is as expected.

Hope someone can help.

Thanks

like image 981
st_clair_clarke Avatar asked Jul 23 '16 08:07

st_clair_clarke


Video Answer


2 Answers

You don't need to inject FormGroup, just use it as a class and instantiate it directly.

So your constructor should be just

constructor() {
    this._form = new FormGroup({
        first: new FormControl('value')
    })
}
like image 170
dfsq Avatar answered Oct 01 '22 01:10

dfsq


This seems to be working in my case, quite similar to yours:

import { FormGroupDirective, NgControl } from '@angular/forms';

//...

constructor(@Host() private hostFormGroup: FormGroupDirective) {
}

// ...

get errorMessage() {
  // Find the control in the Host (Parent) form
  const ctrl: NgControl = this.hostFormGroup.directives
    .find(dir => dir.name === this.ctrlName);
  // ...
}

I'm not sure if there are cleaner ways, but this seems good at the moment.

like image 20
superjos Avatar answered Oct 01 '22 01:10

superjos