0

I was trying to get values using ngOnInit and initialising the form to default values but the form is given undefined. I tried using patchValue also but it doesnt work since form is undefined. Similar code is working in another component but here the form is giving undefined for some reason. Im relatively new to angular so a detailed explanation would be helpful. Here is my typescript code:

export class RecipeEditComponent implements OnInit {
  @ViewChild("recipeForm",{static: false}) recipeForm: NgForm;

  id: number;
  recipe: Recipe;
  editMode = false;

  constructor(
    private route: ActivatedRoute,
    private recipeService: RecipeService
  ) {}

  ngOnInit() {
    this.route.params.subscribe((params: Params) => {
      this.id = +params["id"];
      this.recipe = this.recipeService.getRecipe(this.id);
      this.editMode = params['id'] != null;
      this.initForm()
    });
  }

  initForm(){
    if(this.editMode){
      // this.recipeForm.setValue({
      //   name: "abc",
      //   imagePath: "abc",
      //   description: "abc"
      // })
      console.log(this.recipeForm)
    }
  }
 updateRecipeInfo(form: NgForm) {
    // const newRecipe= new Recipe(values.name, values.imagePath, values.description, this.recipe.ingredients)
    // this.recipeService.updateRecipe(this.id, this.recipe)
    console.log(form)
  }
    
    }

And here is my html code:

<form (ngSubmit)="updateRecipeInfo(recipeForm)" #recipeForm="ngForm">
    <div class="form-group">
      <label for="name">Name</label>
      <input
        id="name"
        class="form-control"
        name="name"
        ngModel
        required
      />
    </div>
    <div>
      <label for="imagePath">Image URL</label>
      <input
        id="imagePath"
        class="form-control"
        name="imagePath"
        ngModel
        required
      />
    </div>
    <div>
      <label for="description">Description</label>
      <textarea
        id="description"
        class="form-control"
        required
        name="description"
        ngModel
        required
      ></textarea>
    </div>
    <div class="align-right-row">
      <button type="submit" class="btn btn-info">Save</button>
      <button type="button" class="btn btn-secondary">Cancel</button>
    </div>
  </form>
Amulya Dubey
  • 157
  • 1
  • 10

3 Answers3

1

Try wrapping the setValue in a setTimeout, like below.

initForm(){
    if(this.editMode){
        setTimeout(() => {
            this.recipeForm.setValue({
                name: "abc",
                imagePath: "abc",
                description: "abc"
            })
            console.log(this.recipeForm);
        }, 0);
    }
}

This will force the form to come into context, and then you can set the value with initial values.

Submitting the form should show the values you type into the form after changing them.

R. Richards
  • 24,603
  • 10
  • 64
  • 64
  • This will not hinder performance in any way, if that is your concern. It is using 0 for the ms time, so there is no delay. The error message I got even recommended using it. – R. Richards May 23 '21 at 19:50
0

Here, you are calling setValue on recipeForm from ngOnInit but using the option {static: false} for @ViewChild reference. @ViewChild elements referenced using {static: false} should only be referenced after AfterViewInit. This may help: https://stackoverflow.com/a/57089572/15762779

  • I used it in some other component and it worked fine. I doubt if thats the problem here. – Amulya Dubey May 23 '21 at 19:55
  • @AmulyaDubey Can you try calling referencing the recipeForm inside ngAfterViewInit()? It may sometimes get the reference based on how you are using it. If you check the angular docs, it clearly states: [View queries are set before the ngAfterViewInit callback is called](https://angular.io/api/core/ViewChild#description) – Saptarshi Majumdar May 23 '21 at 20:08
0

Incase if it is not working on ngInInit(), then use it inside the ngAfterviewInit() method like this.

try either of this

` @ViewChild('yourForm', { static: false }) yourForm: NgForm;

@ViewChildren('yourForm') yourForm: NgForm; `

ngAfterviewInit() {
  console.log(this.yourForm)

}

this will give you ngForm and you can play around it like valuchanges and many more.

Ashwani kumar
  • 99
  • 1
  • 11