2

I want to create custom form element address by implementing ControlValueAccessor.

I am trying to create one AddressComponent, inside which I have multiple input fields. I want to use this component inside a reactive form like below.

address.component.html

<form name="form" class="form_main" #addForm="ngForm" (ngSubmit)="addForm.form.valid && saveAddress()" [formGroup]="addressForm">
  <!-- Address 1 -->
  <mat-form-field class="form-field">
    <input matInput placeholder="Address 1" formControlName="address1" required>
    <mat-error *ngIf="addressForm.get('address1').hasError('required')">
      *Required field
    </mat-error>
  </mat-form-field>

  <!-- Address 2 -->
  <mat-form-field class="form-field">
    <input matInput placeholder="Address 2" formControlName="address2">
  </mat-form-field>

  <!-- Address 3 -->
  <mat-form-field class="form-field">
    <input matInput placeholder="Address 3" formControlName="address3">
  </mat-form-field>

  <!-- Country -->
  <mat-form-field class="form-field">
    <input matInput placeholder="Country" formControlName="country" required>
    <mat-error *ngIf="addressForm.get('country').hasError('required')">
      *Required field
    </mat-error>
  </mat-form-field>

  <!-- State -->
  <mat-form-field class="form-field">
    <input matInput placeholder="State" formControlName="state">
  </mat-form-field>

  <!-- City -->
  <mat-form-field class="form-field">
    <input matInput placeholder="City" formControlName="city" required>
    <mat-error *ngIf="addressForm.get('city').hasError('required')">
      *Required field
    </mat-error>
  </mat-form-field>
</form>

address.component.ts

export class AddressComponent implements OnInit, ControlValueAccessor {

  @ViewChild('addForm')
  public addForm: FormControlName;
  @Input() parentForm: NgForm;
  public addressForm: FormGroup;
  private _address: any = {};
  constructor(
    private fb: FormBuilder,
  ) { }

  ngOnInit() {
    this.addressForm = this.fb.group({
      address1: ['', [Validators.required]],
      address2: [''],
      address3: [''],
      country: ['', [Validators.required]],
      state: ['', [Validators.required]],
      city: ['', [Validators.required]],
    });
  }

  saveAddress() {
    console.log(this._address);
    console.log(this.addressForm.getRawValue());
  }

  propagateChange = (_: any) => {};

  writeValue(obj: any) {
    console.log(obj);  //<-- always getting null
   // this.addForm = obj;  
   // this._address = obj; 
  }

  registerOnChange(fn: any) {
    this.propagateChange = fn;
  }
  registerOnTouched(fn: any) {
    this.propagateChange = fn;
  }
}

customer-registration.component.html

                    <!-- Organization Name -->
                    <mat-form-field class="form-field">
                        <input matInput placeholder="Organization Name" formControlName="cutomerName" required>
                        <mat-error *ngIf="custForm.get('cutomerName').hasError('required')">
                            *Required field
                        </mat-error>
                    </mat-form-field>

                    <!-- Organization Code -->
                    <mat-form-field class="form-field">
                        <input matInput placeholder="Organization Code" formControlName="cutomerCode" required>
                        <mat-hint></mat-hint>
                        <mat-error *ngIf="custForm.get('cutomerCode').hasError('required')">
                            *Required field
                        </mat-error>
                        <mat-error *ngIf="custForm.get('cutomerCode').hasError('isEmployeIdUnique')">
                            Organization Code already available in the system
                        </mat-error>
                    </mat-form-field>

                    <!-- Website -->
                    <mat-form-field class="form-field">
                        <input matInput placeholder="Website" formControlName="website">
                    </mat-form-field>

                    <!-- Telephone -->
                    <mat-form-field class="form-field">
                        <input matInput placeholder="Telephone" name="customerForm.telephone" formControlName="telephone">
                    </mat-form-field>

                    <app-address [parentForm]="primaryAddress" formControlName="primaryAddress" #primaryAddress></app-address>

                    <div class="button-group">
                        <button type="submit" [disabled]="loading" class="btn btn-submit">Submit</button>
                        <button (click)="custForm.reset()" class="btn btn-outline-submit">reset</button>
                    </div>

                </form>

customer-registration.component.ts

    export class CustomerRegistrationComponent implements OnInit {

  @ViewChild('primaryAddress')
  private primaryAddress: AddressComponent;

  public customerForm: NgForm;
  public custForm: FormGroup;
  constructor(
    private fb: FormBuilder,
  ) { }

  ngOnInit() {
    this.custForm = this.fb.group({
      cutomerName: ['', [Validators.required]],
      cutomerCode: ['', [Validators.required]],
      website: [''],
      telephone: ['', [
        Validators.pattern(/^[0-9 ]{1,15}$/)
      ]],
      primaryAddress: new FormControl(),
    });
  }

  registerCusomer() {
    console.log(this.custForm.getRawValue());  //<---- not getting primaryAddress details
    this.primaryAddress.saveAddress();
  }
}

I don't know why I am not getting primaryAddress details while calling this.custForm.getRawValue() onSubmit of form.

1 Answer 1

7

add this code to registerOnChange:

this.addressForm.valueChanges.subscribe(() => {
  fn(this.addressForm.value);
});
Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.