Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

ERROR Error: formControlName must be used with a parent formGroup directive

Tags:

html

angular

It throws me this error in console, however the form is working right whenever I clic.

Seriously, I don't see the mistake, I have another template with the same syntax and it doesn't throw me this error

   <div class="container-fluid">
      <div class="row">
        <div class="col-md-5">
          <div class="card">
            <div class="header">
              <h4 class="title">Comparativa mensual</h4>
              <p class="category">Año actual</p>
            </div>
            <div class="content">
              <app-pie-graph #graphmonths></app-pie-graph>
            </div>
          </div>
        </div>
        <div class="col-md-7">
        <div class="card ">
          <div class="header">
            <div class="formGroup">
              <form [formGroup]="dataForm" (ngSubmit)="submit($event)">
                <h4 class="title inline">Comparativa diaria</h4>
                <my-date-range-picker  name="mydaterange"  [options]="myOptions" formControlName="myDateRange"></my-date-range-picker>
                <button type="submit" class="btn btn-primary">Consultar</button>
              </form>
            </div>
            <p class="category">Vista de una semana</p>
          </div>
          <div class="content">
            <div class="row">
              <div class="col-sm-8">
                <app-pie-graph #graphdays></app-pie-graph>
              </div>
            </div>
          </div>
        </div>
      </div>
    </div>

Error

ERROR Error: formControlName must be used with a parent formGroup directive.  You'll want to add a formGroup
       directive and pass it an existing FormGroup instance (you can create one in your class).

      Example:


    <div [formGroup]="myGroup">
      <input formControlName="firstName">
    </div>

    In your class:

    this.myGroup = new FormGroup({
       firstName: new FormControl()
    });

UPDATE: ts file------------------------------------------------------------------------------------------------------------------------------------------------

import { Component, ViewChild, OnInit, AfterViewInit, QueryList } from '@angular/core';
import { LinearGraphComponent } from '../../shared/graph/linear-graph/linear-graph.component';
import { PieGraphComponent } from '../../shared/graph/pie-graph/pie-graph.component';
import { Validators, FormGroup, FormControl } from '@angular/forms'
import { Data } from '../data';
import { ActivatedRoute } from '@angular/router';


@Component({
  selector: 'app-overview',
  templateUrl: './overview.component.html',
  styleUrls: ['./overview.component.css']
})
export class OverviewComponent implements AfterViewInit, OnInit{

  @ViewChild('graphdays') private pieGraphDays: PieGraphComponent;
  @ViewChild('graphmonths') private pieGraphMonths: PieGraphComponent;
  @ViewChild('generaloverview') private linearGraph: LinearGraphComponent;

  //COMMON
  public getDataRetriever(): Data { return this.dataRetriever; }
  //COMMON
  //private disableButton(){ this.blocked = true; }
  //COMMON
  //private activateButton(){ this.blocked = false; }

  //COMMON VARIABLE
  private userid = parseInt(this.route.parent.snapshot.params.id);

  private dataForm = new FormGroup({
    myDateRange: new FormControl(null, Validators.required)
  });

   constructor(
    private dataRetriever: Data,
    private route: ActivatedRoute
  ){
  }

  ngOnInit(){


  }

  private getMonthAgo(since: Date): Date{
    var monthAgo = new Date(since.getTime());
    monthAgo.setMonth(monthAgo.getMonth() - 3);
    monthAgo.setHours(8, 0, 0, 0);
    return monthAgo;
  }

  private displayLastMonthDaysLinear(){
    var that = this;
    var yesterday = this.getYesterday();
    var monthAgo = this.getMonthAgo(yesterday);
    this.getDataRetriever().getRangeDays(this.userid, monthAgo, yesterday, function(){
      let data = that.getDataRetriever().getData();
      let labels = that.getDataRetriever().getXLabels();
      console.log(labels);
      that.linearGraph.setChart(data, labels);
    });

  }

  private displayLastWeekPie(){
    var that = this;
    var monday = this.getMondayCurrentWeek();
    var yesterday = this.getYesterday();
    if(monday.getDate() === new Date().getDate()) //If today is monday
      monday.setDate(monday.getDate()-7); //Get monday from previous week
    this.getDataRetriever().getRangeDays(this.userid, monday, yesterday, function(){
      let data = that.getDataRetriever().getData();
      let labels = that.getDataRetriever().getXLabels();
      console.log(labels);
      that.pieGraphDays.setChart(data[0].data, labels);
    });
  }

  private displayLastMonthsPie(){
    var now = new Date();
    var newYear = new Date(now.getFullYear(), 0, 1, 8, 0, 0, 0);
    var last = new Date(new Date().setMonth(now.getMonth()-1));
    var that = this;
    if(newYear.getMonth() === now.getMonth()) //If we are in January (spetial case)
      newYear.setFullYear(newYear.getFullYear() - 1); //Get January from past year
    this.getDataRetriever().getCountingPerMonth(this.userid, newYear, last, function(){
      let data = that.getDataRetriever().getData();
      let las = that.getDataRetriever().getXLabels();
      console.log(data);
      that.pieGraphMonths.setChart(data, las);
    });

  }


  private getDaysToMonth(month, year): number[] { //month not included
     var date = new Date(year, month, 1);
     var days = [];
     while (date.getMonth() < month) {
        days.push(new Date(date).setHours(8,0,0,0));
        date.setDate(date.getDate() + 1);
     }
     return days;
  }

  private getYesterday(): Date{
    var today = new Date();
    today.setDate(today.getDate() - 1);
    today.setHours(8,0,0,0);
    return today
  }

  private getMondayCurrentWeek(): Date{
    var d = new Date();
    var day = d.getDay(),
      diff = d.getDate() - day + (day == 0 ? -6:1); // adjust when day is sunday
    d.setDate(diff);
    d.setHours(8,0,0,0);
    return d;
  }

  ngAfterViewInit(){
    this.displayLastMonthsPie();
    this.displayLastWeekPie();
    this.displayLastMonthDaysLinear();
    console.log(this.linearGraph);
  }

  submit(){
    let range = this.getPickedDayRange();
    var that = this;
    this.getDataRetriever().getRangeDays(this.userid, range[0], range[1], function(){
      let data = that.getDataRetriever().getData();
      let labels = that.getDataRetriever().getXLabels();
      that.pieGraphDays.setChart(data[0].data, labels);
    });
  }

  //COMMON CLASS
  private getPickedDayRange(): Date[]{
    var begDate = new Date(this.dataForm.value.myDateRange.beginJsDate);
    var endDate = new Date(this.dataForm.value.myDateRange.endJsDate);
    return [begDate, endDate];
  }

}
like image 883
Sergio Barbero Avatar asked Oct 16 '22 19:10

Sergio Barbero


1 Answers

I pieced together the answers from another post.

The short answer is that you have to declare the formGroup in the parent component, then pass in the formGroup to the child component.

app.component.ts

feedbackValues = [1,2,3,4,5];

constructor(private formBuilder: FormBuilder) {
    this.surveyForm = this.formBuilder.group({
      rowForm: this.formBuilder.group({
        rating: ['']
      })
    });

app.component.html

<form [formGroup]="surveyForm" (ngSubmit)="onSubmit()" >

  <app-survey-row [feedbackValues]=feedbackValues [parentGroup]="surveyForm"></app-survey-row>

  <button type="submit">Submit</button>
</form>

survey-row.component.ts

export class SurveyRowComponent implements OnInit {

  @Input() feedbackValues;
  @Input() parentGroup: FormGroup;

  constructor( private formBuilder: FormBuilder) {
  }

  ngOnInit() {
  }
}

survey-row.component.html

<div [formGroup]="parentGroup">
  <div formGroupName="rowForm">
    <div *ngFor="let val of feedbackValues; let i = index">
      <input id="{{i+1}}" type="radio" value="{{i+1}}" formControlName="rating">
      <label for="{{i+1}}">{{i+1}}</label>
    </div>

  </div>
</div>

Notice how the [formGroup] is passed in by the parent component, and the formGroupName is not declared in survey-row, but in app.component.ts

like image 91
Jon Avatar answered Oct 20 '22 22:10

Jon