如何使用 ngOnInit 初始化反应式表单?

问题描述 投票:0回答:1

我一直在尝试使用我订阅的可观察对象来初始化我的反应式表单。在表单类模板中,我使用 ngOnInit 钩子来获取我想要的对象,在本例中为产品对象。

第一个代码是类模板,第二个代码是 html 模板,我在其中使用行为主题传递产品。

然后,我会收到错误“属性‘产品’在初始化之前被使用。”在表单控件名称实例的第一行。我认为这是因为产品表单是在 ngOnInit 挂钩之前创建的,因此它无法访问该对象。有任何想法吗?被困在这里这么久了,将不胜感激任何帮助!

产品表单组件.ts:

export class ProductFormComponent {

  productReceived: Subscription;
  editMode: boolean = false;
  product: product;


  constructor(private productService: ProductService) { }

  ngOnInit() {
    this.productReceived = this.productService.$emitProduct.subscribe((product: product) => {
      if (product) {
        this.product = product;
        this.editMode = true;
      }
    });

  }

   productForm = new FormGroup({
    name: new FormControl(`${this.product}`, [Validators.required, Validators.minLength(3)]), // THIS LINE
    description: new FormControl(''),
    specification: new FormControl(''),
    price: new FormControl(''),
    imagePath: new FormControl(''),
    warranty: new FormControl(''),
  });

  ngOnDestroy() {
    this.productReceived.unsubscribe();
  }

}

product-item.component.html:

<div style="cursor: pointer; width: 450px;" class="card rounded p-3"
  aria-current="true">
  <div>
    <div class="d-flex w-100 justify-content-between mb-1">
      <div class="d-flex" style="gap: 0.75rem;">
        <h5>{{ product.name | titlecase}}</h5>
        <span style="color: darkred;">${{product.price}}</span>
      </div>
      <div class="dropdown">
        <button class="btn btn-dark dropdown-toggle" type="button" data-bs-toggle="dropdown" aria-expanded="false">
          Manage Product
        </button>
        <ul class="dropdown-menu">
          <li><a class="dropdown-item" >Add to Cart</a></li>
          <li><a class="dropdown-item" data-bs-toggle="modal" data-bs-target="#staticBackdrop" style="cursor: pointer;" (click)="formOpen(product)">Edit</a></li>
          <li><a class="dropdown-item" style="cursor: pointer;">Delete</a></li>
        </ul>
      </div>
    </div>
    <div class="d-flex flex-row align-items-center" [routerLink]="product.name" (click)="emitProduct(product)">
      <img [src]="product.imagePath[0]" style="max-height: 175px">
      <ul class="product-desc">
        <li>{{productDescList[0]}}</li>
        <li>{{productDescList[1]}}</li>
      </ul>
    </div>
  </div>
</div>

<app-modal-pop></app-modal-pop>

product-form.component.html:

<form [formGroup]="productForm">

  <h5>{{editMode? 'Edit Product': 'Create Product'}}</h5>

  <div>
    <app-input-field label="Name" [control]="productForm.get('name')"></app-input-field>
  </div>
  <div>
    <app-input-field label="Description" [control]="productForm.get('description')"></app-input-field>
  </div>
  <div>
    <app-input-field label="Specification" [control]="productForm.get('specification')"></app-input-field>
  </div>
  <div>
    <app-input-field label="Price" [control]="productForm.get('price')"></app-input-field>
  </div>
  <div>
    <app-input-field label="Image Path" [control]="productForm.get('imagePath')"></app-input-field>
  </div>
  <div>
    <app-input-field label="Warranty" [control]="productForm.get('warranty')"></app-input-field>
  </div>

  <button type="submit" class="btn btn-secondary">Create</button>

</form>

输入字段.component.html:

<label class="label">{{label}}:</label>
<input type="text" [formControl]="control" id="name" [ngClass]="{'alert-danger': showErrors()}">
<ng-container *ngIf="control.errors && control.dirty && control.touched">
  <div style="color: red;" *ngIf="control.errors.required">
    Name is required!
  </div>
  <div style="color: red;" *ngIf="control.errors.minlength">
    3 minimum characters!
  </div>
</ng-container>

angular angularjs typescript angular-forms
1个回答
0
投票

您正在创建

this.product
之前访问它。

this.productService.$emitProduct.subscribe
它在之后被触发,您在表单初始化中使用
this.product
它。

在构造函数中创建表单并在 OnInit 函数中初始化它

export class ProductFormComponent {

  productReceived?: Subscription;
  editMode: boolean = false;
  product?: product;
  productForm: FormGroup;


  constructor(private productService: ProductService) { 
      this.productForm = new FormGroup({
          name: new FormControl('', [Validators.required,Validators.minLength(3)]),
          description: new FormControl(''),
          specification: new FormControl(''),
          price: new FormControl(''),
          imagePath: new FormControl(''),
          warranty: new FormControl(''),
      });
    }

    ngOnInit() {
        this.productReceived = this.productService.$emitProduct.subscribe((product: product) => {
            if (product) {
                this.product = product;
                this.editMode = true;
                this.productForm.patchValue({...this.product})
            }
        });
      }

    ngOnDestroy() {
      this.productReceived.unsubscribe();
    }
}
© www.soinside.com 2019 - 2024. All rights reserved.