ERROR TypeError: Cannot read properties of undefined (reading 'companyForm')

Discussão em 'Angular' iniciado por lordlaurent, Dezembro 8, 2024.

  1. lordlaurent

    lordlaurent Guest

    I'm trying to fetch data like boolean isCompany and Strings companyName and nip from users table from backend and set it as default in fields in the form. All other data are patched correctly. There is only a problem with these.

    The data are being feched correctly and they exist in database. The problem is I get this create-order.component.html:14 ERROR TypeError: Cannot read properties of undefined (reading 'companyForm') error and these to fields remain empty in the form.

    This is how I initialize form in form.service.ts:

    initCompanyForm(): FormGroup {
    return new FormGroup({
    companyName: new FormControl('', {}),
    nip: new FormControl('', {
    validators: [Validators.pattern(/^\d{10}$/)]
    })
    });
    }


    This is company-form.component.ts:

    export class CompanyFormComponent {
    companyForm: FormGroup;

    constructor(private formService: FormService) {
    this.companyForm = this.formService.initCompanyForm();
    }

    get controls() {
    return this.companyForm.controls as { [key: string]: FormControl };
    }

    getErrorMessage(control: FormControl): string {
    return this.formService.getErrorMessage(control);
    }
    }


    This Angular component create-order.component manages a multi-step order form with child components for customer, address, delivery, company, and additional information. The issue arises because the CompanyFormComponent is not fully initialized when fetchUserProfile() tries to patch its form values, resulting in undefined errors. Even with ngAfterViewInit, the asynchronous nature of the profile fetch (profileService.getUserProfile()) causes a timing mismatch. I guess the problem is that the profile data arrives before the CompanyFormComponent is ready.

    export class CreateOrderComponent implements OnInit, AfterViewInit {
    errorMsg: null | string = null;
    saveShipping = false;
    isAuthenticated = false;
    isCompany = false;

    @ViewChild(CustomerFormComponent) customerFormComp!: CustomerFormComponent;
    @ViewChild(AddressFormComponent) addressFormComp!: AddressFormComponent;
    @ViewChild(DeliveryFormComponent) deliveryFormComp!: DeliveryFormComponent;
    @ViewChild(CompanyFormComponent) companyFormComp!: CompanyFormComponent;
    @ViewChild(InfoFormComponent) infoFormComp!: InfoFormComponent;

    constructor(
    private location: Location,
    private router: Router,
    private ordersService: OrdersService,
    private profileService: ProfileService,
    private authService: AuthService
    ) {}

    ngOnInit(): void {
    const locationState = this.location.getState() as {
    summaryPrice: undefined | number;
    navigationId: number;
    };

    if (!locationState.summaryPrice) {
    this.router.navigate(['']);
    }

    this.checkIfUserIsLoggedIn();
    }

    ngAfterViewInit(): void {
    if (this.isAuthenticated) {
    this.fetchUserProfile();
    }
    }

    checkIfUserIsLoggedIn(): void {
    this.authService.isLoggedIn().subscribe({
    next: (response) => {
    this.isAuthenticated = response.message;
    if (this.isAuthenticated) {
    this.fetchUserProfile();
    }
    },
    error: (err) => {
    this.isAuthenticated = false;
    console.error('Error checking login status:', err);
    }
    });
    }

    fetchUserProfile(): void {
    this.profileService.getUserProfile().subscribe({
    next: (profile) => {
    console.log('User profile:', profile);

    this.customerFormComp.customerForm.patchValue({
    firstName: profile.firstName || '',
    lastName: profile.lastName || '',
    email: profile.email || ''
    });

    if (profile.phone) {
    this.customerFormComp.controls.phone.setValue(profile.phone);
    }

    this.addressFormComp.addressForm.patchValue({
    city: profile.city || '',
    street: profile.street || '',
    number: profile.number || '',
    postCode: profile.postCode || ''
    });

    if (profile.company) {
    this.isCompany = true;

    if (this.companyFormComp?.companyForm) { // this if omits the error, but doesn't solve the problem
    console.log('Patching company form with:', {
    companyName: profile.companyName,
    nip: profile.nip
    });
    this.companyFormComp.companyForm.enable();
    this.companyFormComp.companyForm.patchValue({
    companyName: profile.companyName || '',
    nip: profile.nip || ''
    });
    }
    } else {
    this.isCompany = false;
    if (this.companyFormComp?.companyForm) {
    this.companyFormComp.companyForm.reset();
    this.companyFormComp.companyForm.disable();
    }
    }
    },
    error: (err) => {
    this.errorMsg = 'Nie udało się załadować danych użytkownika';
    console.error('Error fetching user profile:', err);
    }
    });
    }

    onCompanyChange(): void {
    console.log('Checkbox changed:', this.isCompany);
    if (this.isCompany) {
    console.log('Enabling company fields...');
    this.companyFormComp.companyForm.enable();
    } else {
    console.log('Disabling and resetting company fields...');
    this.companyFormComp.companyForm.reset();
    this.companyFormComp.companyForm.disable();
    }
    }

    order(): void {
    if (
    this.customerFormComp.customerForm.valid &&
    this.addressFormComp.addressForm.valid &&
    this.deliveryFormComp.deliveryForm.valid &&
    (!this.isCompany || this.companyFormComp.companyForm.valid)
    ) {
    const orderData = {
    address: this.addressFormComp.addressForm.getRawValue(),
    deliver: this.deliveryFormComp.deliveryForm.getRawValue(),
    customerDetails: this.customerFormComp.customerForm.getRawValue(),
    isCompany: this.isCompany,
    companyName: this.isCompany
    ? this.companyFormComp.companyForm.get('companyName')?.value
    : null,
    nip: this.isCompany
    ? this.companyFormComp.companyForm.get('nip')?.value
    : null,
    info: this.infoFormComp.infoForm.get('info')?.value || null
    };

    console.log(
    'Order data being sent to backend:',
    JSON.stringify(orderData, null, 2)
    );

    this.ordersService.addOrder(orderData).subscribe({
    next: () => {
    if (this.saveShipping && this.isAuthenticated) {
    this.saveShippingDetails(orderData.address);
    }
    },
    error: (err) => {
    this.errorMsg = err;
    console.error('Order submission error:', err);
    }
    });
    } else {
    console.warn('Form is invalid');
    }
    }


    All the form components are in create-order.component.

    [​IMG]

    [​IMG]

    Continue reading...

Compartilhe esta Página