Реактивный FormsModule в Angular2 - PullRequest
0 голосов
/ 04 февраля 2019

Я пытался добавить FormsArray в свой проект при использовании ReactiveFormsModule, но я получаю сообщение об ошибке, и оно отображается как: -

Не удается найти элемент управления с неопределенным атрибутом имени .а также мы не можем добавить FormsArray с помощью шаблонно-управляемой формы?

Ниже приведен мой код для этого.

recipe-edit.component.ts

<div class="row">
<div class="col-xs-12">
<form [formGroup]="recipeform" (ngSubmit)="onsubmit()" #f="ngForm">
  <div class="row">
    <div class="col-xs-12">
      <button
        type="submit"
        class="btn btn-success" 

        >Save</button>
      <button type="button" class="btn btn-danger" >Cancel</button>
    </div>
  </div>
  <div class="row">
    <div class="col-xs-12">
      <div class="form-group">
        <label for="name">Name</label>
        <input
          type="text"
          id="name"
          formControlName="name"
          class="form-control">
      </div>
    </div>
  </div>
  <div class="row">
    <div class="col-xs-12">
      <div class="form-group">
        <label for="imagePath">Image URL</label>
        <input
          type="text"
          id="imagePath"
          formControlName="image"
          class="form-control"
          >
      </div>
    </div>
  </div>
  <div class="row">
    <div class="col-xs-12" >
      <img  class="img-responsive">
    </div>
  </div>
  <div class="row">
    <div class="col-xs-12">
      <div class="form-group">
        <label for="description">Description</label>
        <textarea
          type="text"
          id="description"
          class="form-control"
          formControlName="description"
          rows="6"></textarea>
      </div>
    </div>
  </div>
  <div class="row">
    <div class="col-xs-12" >
      <div
        class="row"
       formArrayName="ingredients"
       *ngFor="let ctrl of recipeform.get('ingredients').controls;let i=index"
        [formGroupName]="i"          
        style="margin-top: 10px;">
        <div class="col-xs-8">
          <input
            type="text"
            formControlName="name"
            class="form-control"
           >
        </div>
        <div class="col-xs-2">
          <input
            type="number"
            class="form-control"
            formControlName="amount"
           >
        </div>
        <div class="col-xs-2">
          <button
            type="button"
            class="btn btn-danger"
           >X</button>
        </div>
      </div>
      <hr>
      <div class="row">
        <div class="col-xs-12">
          <button
            type="button"
            class="btn btn-success"

            >Add Ingredient</button>
        </div>
      </div>
    </div>
  </div>
</form>

recipe-edit.component.ts

import { Component, OnInit, ViewChild } from '@angular/core';
import {NgForm, FormGroup, FormControl, FormArray} from 
'@angular/forms';
import { Recipeservice } from '../recipe.service';
import { ActivatedRoute, Router } from '@angular/router';
@Component({
 selector: 'app-recipe-edit',
templateUrl: './recipe-edit.component.html',
styleUrls: ['./recipe-edit.component.css']
})
export class RecipeEditComponent implements OnInit {
@ViewChild('f') recipeform:FormGroup
id:number
editmode=false
constructor(private reservice:Recipeservice,private 
route:ActivatedRoute,router:Router) { }

ngOnInit() {
this.route.params.subscribe(
  (params)=>{
    this.id=+params['id']
    console.log(this.id)

    this.initform()
  }
)


}
 onsubmit(){
console.log(this.recipeform)
}
private initform(){
let recipename=''
let recipeimage=''
let recipedescription=''
let recipeingredients=new FormArray([])
this.editmode=true
if(this.editmode){
  const recipe=this.reservice.getrecipe(this.id)
  recipename=recipe.name
  recipeimage=recipe.imagepath
  recipedescription=recipe.description
  if(recipe.ingredients!=null){
    for(let ingredient of recipe.ingredients){
      recipeingredients.push(new FormGroup({
        'name':new FormControl(ingredient.name),
        'amount':new FormControl(ingredient.amount)
      }))
    }
  }
}
this.recipeform=new FormGroup({
  'name':new FormControl(recipename),
  'image':new FormControl(recipeimage),
  'description':new FormControl(recipedescription),
  'ingredients':recipeingredients
})
}

 }

Ответы [ 2 ]

0 голосов
/ 04 февраля 2019

Я полностью согласен с рекомендациями @ DeborahK в предыдущем ответе , и вы должны следовать им при использовании реактивных форм.

Однако это не такпричина вашей ошибки.В вашем HTML-шаблоне у вас неправильная иерархия элемента управления FormArray.Это должен быть FormArray -> FormGroup -> FormControl, например:

<div class="row"
        formArrayName="ingredients"
        *ngFor="let ctrl of recipeform.get('ingredients').controls;let i=index"
        style="margin-top: 10px;">
    <div [formGroupName]="i">
        <div class="col-xs-8">
            <input type="text"
                    formControlName="name"
                    class="form-control">
        </div>
        <div class="col-xs-2">
            <input type="number"
                    class="form-control"
                    formControlName="amount">
        </div>
        <div class="col-xs-2">
            <button type="button"
                    class="btn btn-danger">
                X
            </button>
        </div>
    </div>
</div>

Как видите, я обернул name и amount controlв пределах div и переместил [formGroupName] в эту оболочку div.Я не тестировал код, но он должен решить вашу проблему.

0 голосов
/ 04 февраля 2019

Настоятельно рекомендуется тем, кто писал угловые формы для , а не , смешивать шаблонно-управляемые и реактивные формы.FormArray является частью Реактивных форм.

В вашем коде есть несколько «управляемых шаблонами» техник форм, которые вы должны рассмотреть, например:

@ViewChild('f') recipeform:FormGroup

Вы определяетеrecipeform FormGroup в вашем коде, затем генерирует ссылку на него в вашем шаблоне, а затем передает эту ссылку обратно в ваш код.(Я удивлен, что это не вызывает ошибку.)

Я бы порекомендовал:

1) Удаление #f="ngForm" из вашего шаблона.Это необходимо только для форм-управляемых форм.

2) Замена @ViewChild('f') recipeform:FormGroup только объявлением для recipeform: FormGroup.

3) Использование FormBuilder вместо экземпляров FormGroup и FormControl.

4) Это асинхронный вызов: const recipe=this.reservice.getrecipe(this.id), если да, вам нужно использовать subscribe для получения данных.

Вот пример одной из моих реактивных форм с использованием FormBuilderи FormArray:

export class CustomerComponent implements OnInit {
  customerForm: FormGroup;

      ngOnInit() {
        this.customerForm = this.fb.group({
          firstName: ['', [Validators.required, Validators.minLength(3)]],
          lastName: ['', [Validators.required, Validators.maxLength(50)]],
          addresses: this.fb.array([this.buildAddress()])
        });
      }

      addAddress(): void {
        this.addresses.push(this.buildAddress());
      }

      buildAddress(): FormGroup {
        return this.fb.group({
          addressType: 'home',
          street1: ['', Validators.required],
          street2: '',
          city: '',
          state: '',
          zip: ''
        });
      }
}

Вы можете найти полный рабочий пример здесь: https://github.com/DeborahK/Angular-ReactiveForms

У меня есть второй пример в том же репо, который включает в себя код параметра, аналогичный тому, что выделать:

  ngOnInit(): void {
    this.productForm = this.fb.group({
      productName: ['', [Validators.required,
                         Validators.minLength(3),
                         Validators.maxLength(50)]],
      tags: this.fb.array([]),
      description: ''
    });

    // Read the product Id from the route parameter
    this.sub = this.route.paramMap.subscribe(
      params => {
        const id = +params.get('id');
        this.getProduct(id);
      }
    );
  }

  getProduct(id: number): void {
    this.productService.getProduct(id)
      .subscribe(
        (product: Product) => this.displayProduct(product),
        (error: any) => this.errorMessage = <any>error
      );
  }

  displayProduct(product: Product): void {
    if (this.productForm) {
      this.productForm.reset();
    }
    this.product = product;

    // Update the data on the form
    this.productForm.patchValue({
      productName: this.product.productName,
      description: this.product.description
    });
    this.productForm.setControl('tags', this.fb.array(this.product.tags || []));
  }

Дайте мне знать, если у вас есть какие-либо вопросы по поводу любого из примеров.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...