Массив по-прежнему не определен, даже в методе подписки - PullRequest
0 голосов
/ 24 апреля 2020

В моем приложении angular массив productLocations назначается в методе ngOnInit в подписке, а затем используется в методе, но он все еще не определен. При поиске в Stackoverflow все говорят о переносе назначения в подписке. Это уже в подписке, но я получаю ошибку. Как правильно выполнить вещи в последовательности?

ERROR TypeError: Cannot read property 'forEach' of undefined
    at AddProductComponent.populateProductLocation

Файл компонента

export class AddProductComponent implements OnInit, OnDestroy {

  form: FormGroup;
  productManufacturerOptions: ProductManufacturer[] = [];
  filteredProductManufacturerOptions: Observable<ProductManufacturer[]>;
  productModelOptions: ProductModel[] = [];
  filteredProductModelOptions: Observable<ProductModel[]>;
  productCategoryOptions: ProductCategory[] = [];
  filteredProductCategoryOptions: Observable<ProductCategory[]>;

  product: Product = new Product();
  branches: Branch[] = [];
  productLocations: ProductLocation[];
  productPrices: ProductPrice[];
  priceLists: PriceList[] = [];
  editMode = false;
  private _unsubscribeAll: Subject<any>;
  fileToUpload: File = null;

  constructor(
    private http: HttpClient,
    private _formBuilder: FormBuilder,
    private productManufacturerService: ProductManufacturerService,
    private productModelService: ProductModelService,
    private productCategoryService: ProductCategoryService,
    private productService: ProductService,
    private branchService: BranchService,
    private router: Router,
    private route: ActivatedRoute,
    private _fuseProgressBarService: FuseProgressBarService,
    private priceListService: PriceListService,
    private cd: ChangeDetectorRef
  ) {
    this._unsubscribeAll = new Subject();
    this.initForm();
    if (this.route.snapshot.url[0].path == 'edit' && localStorage.getItem("editProductId")) {
      this.editMode = true;
    }
  }

  ngOnInit(): void {
    this._fuseProgressBarService.show();
    if (this.editMode) {
      this.productService.get(localStorage.getItem("editProductId"))
        .subscribe((result: any) => {
          this.product = new Product(result);
          console.log("Product", this.product);
          // this.productLocations = result.locations;
          this.productLocations = this.product.locations;
          this.productPrices = this.product.prices;
          this.populateUpdateData(result);
        });
    }

    forkJoin([this.productManufacturerService.getList(),
    this.productModelService.getList(),
    this.productCategoryService.getList(),
    this.branchService.getList(),
    this.priceListService.getList()
    ])
      .subscribe((results: any) => {
        this.productManufacturerOptions = results[0];
        this.productManufacturerStart();

        this.productModelOptions = results[1];
        this.productModelStart();

        this.productCategoryOptions = results[2];
        this.productCategoryStart();

        this.branches = results[3];
        this.priceLists = results[4];
      },
        error => { },
        () => {
          if (this.editMode) {
            this.populateProductLocations();
            this.populatePriceLists();
          }
          else {
            this.initProductLocations();
            this.initPriceLists();
          }
          this._fuseProgressBarService.hide();
        });
  }

  initForm() {
    this.form = this._formBuilder.group({
      id: [''],
      partNumber: ['', Validators.required],
      description: ['', Validators.required],
      replaceNumbers: this._formBuilder.array([]),
      manufacturer: [null, Validators.required],
      model: [null, Validators.required],
      category: [null, Validators.required],
      cost: ['', Validators.required],
      locations: this._formBuilder.array([]),
      prices: this._formBuilder.array([]),
      featuredImage: [null]
    });
  }

  initProductLocations() {
    this.branches.forEach(branch => {
      this.initProductLocation(branch)
    });
  }
  initProductLocation(branch) {
    const control = <FormArray>this.form.controls['locations'];
    var a = this._formBuilder.group({
      branch: [branch, Validators.required],
      location: [null, Validators.required],
      quantity: [null, Validators.required]
    });
    control.push(a);
  }
  populateProductLocations() {
    this.branches.forEach(branch => {
      this.populateProductLocation(branch)
    });
  }
  populateProductLocation(branch) {
    const control = <FormArray>this.form.controls['locations'];
    var a;
    var productLocationBranchIds = [];    
    this.productLocations.forEach(productLocation => {
      productLocationBranchIds.push(productLocation.branch.id)
    });
    console.log("ProdIDS", productLocationBranchIds);
    if (productLocationBranchIds.includes(branch.id)) {
      this.productLocations.forEach(productLocation => {
        if (branch.id == productLocation.branch.id) {
          a = this._formBuilder.group({
            branch: [productLocation.branch, Validators.required],
            location: [productLocation.location, Validators.required],
            quantity: [productLocation.quantity, Validators.required]
          });
        }
      });
    }
    else {
      console.log("In else");
      a = this._formBuilder.group({
        branch: [branch, Validators.required],
        location: [null, Validators.required],
        quantity: [null, Validators.required]
      });
    }
    control.push(a);
  }


  initPriceLists() {
    this.priceLists.forEach(priceList => {
      this.initPriceList(priceList)
    });
  }
  initPriceList(priceList) {
    const control = <FormArray>this.form.controls['prices'];
    var a = this._formBuilder.group({
      priceList: [priceList, Validators.required],
      price: [null, Validators.required]
    });
    control.push(a);
  }

  populatePriceLists() {
    this.priceLists.forEach(priceList => {
      this.populatePriceList(priceList)
    });
  }
  populatePriceList(priceList) {
    const control = <FormArray>this.form.controls['prices'];
    var a;
    var productPricesPriceListIds = [];
    this.productPrices.forEach(productPrice => {
      productPricesPriceListIds.push(productPrice.priceList.id)
    });
    if (productPricesPriceListIds.includes(priceList.id)) {
      this.productPrices.forEach(productPrice => {
        if (priceList.id == productPrice.priceList.id) {
          a = this._formBuilder.group({
            priceList: [productPrice.priceList, Validators.required],
            price: [productPrice.price, Validators.required]
          });
        }
      });
    }
    else {
      a = this._formBuilder.group({
        priceList: [priceList, Validators.required],
        price: [null, Validators.required]
      });
    }
    control.push(a);
  }

  get replaceNumbers(): FormArray {
    return this.form.get('replaceNumbers') as FormArray;
  }
  createReplaceNumber(): FormGroup {
    return this._formBuilder.group({
      partNumber: ['', Validators.required]
    });
  }
  addExistingReplaceNumber(value): FormGroup {
    return this._formBuilder.group({
      partNumber: [value, Validators.required]
    });
  }
  addReplaceNumber() {
    this.replaceNumbers.push(this.createReplaceNumber());
  }
  removeReplaceNumber(index: number) {
    this.replaceNumbers.removeAt(index);
  }

  populateUpdateData(product) {
    this.form.get('id').setValue(product.id);
    this.form.get('partNumber').setValue(product.partNumber);
    this.form.get('description').setValue(product.description);
    this.form.get('manufacturer').setValue(product.manufacturer);
    this.form.get('model').setValue(product.model);
    this.form.get('category').setValue(product.category);
    this.form.get('cost').setValue(product.cost);
    let rs = product.replaceNumbers;
    rs.forEach(element => {
      this.replaceNumbers.push(this.addExistingReplaceNumber(element.partNumber));
    });
  }

  ngOnDestroy(): void {
    this._unsubscribeAll.next();
    this._unsubscribeAll.complete();
  }
}

1 Ответ

1 голос
/ 24 апреля 2020

Скорее всего, это происходит потому, что следующий блок выполняется быстрее, чем подписка:

          if (this.editMode) {
            this.populateProductLocations();
            this.populatePriceLists();
          }

Чтобы убедиться в этом, вы можете сделать console.log (или поставить точку останова) в этом блоке, а также в подписка, в которой вы присваиваете значение.

Вы должны рассмотреть возможность рефакторинга вашего кода, чтобы this.populateProductLocations() следовал после this.productLocations = this.product.locations; в том же блоке кода, или ждал, пока this.productService.get(localStorage.getItem("editProductId")) завершится (возможно, с swithcMap, combineLatest или withLatestFrom).

с ForkJoin

forkJoin также должно работать, поскольку оно ожидает завершения всех наблюдаемых, и, поскольку у вас уже есть это, вы можете переместите свой код в forkJoin, что-то вроде этого (я закомментировал существующий код, чтобы уточнить, что было добавлено):

forkJoin([
  // this.productManufacturerService.getList(),
  // this.productModelService.getList(),
  // this.productCategoryService.getList(),
  // this.branchService.getList(),
  // this.priceListService.getList(),
  this.productService.get(localStorage.getItem("editProductId"))
])
  .subscribe((results: any) => {
    // this.productManufacturerOptions = results[0];
    // this.productManufacturerStart();

    // this.productModelOptions = results[1];
    // this.productModelStart();

    // this.productCategoryOptions = results[2];
    // this.productCategoryStart();

    // this.branches = results[3];
    // this.priceLists = results[4];

    this.product = new Product(result);
    this.productLocations = this.product.locations;
    this.productPrices = this.product.prices;
    this.populateUpdateData(results[5]);
  },
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...