1

I've got two sections of forms - correspondence address and residential address. The goal is to copy/pass values from one field to another if a checkbox is checked. Kindly see below use case

  • populate the correspondence address fields with the values of the residential address form fields iff a checkbox (same as residential address) is checked
  • Should any form field in the residential address change after checking the checkbox, pass the change(s) realtime to the field in the correspondence
    address and
  • lastly, clear the form values in the correspondence address if the checkbox is unchecked. Below is what i've tried

Component.ts

populateCorrespondenceAdd(event) {
    //console.log(event.checked)
    if (event.checked) {
        [...]
        this.correspondenceHouseNumber = 
        this.residentialHouseNumber;
        this.correspondenceStreetName = 
        this.enrollee.residentialStreetName;
        this.enrollee.correspondenceLGA = 
        this.enrollee.residentialLGA;
        [...]
    }
}

component.html

<mat-checkbox [(ngModel)]="populateCorrespondenceaddress" (change)="populateCorrespondenceAdd($event)"
                formControlName="populateCorrespondenceadd" value="true">Same as residential address?)</mat-checkbox>

The code above doesn't quite meet expectation as (i) unchecking the checkbox doesn't clear the form fields (ii) after checking the checkbox, if there's any change(s) in any of the form fields in the residential address section, the correspondence form fields doesn't update to reflect the changes. N:B: The fields are in one form group

Kindly guide.

1

1 Answer 1

2

I've simplified a bit your example and used:
- sending address
- billing address

Otherwise I think it's pretty much the same :)

TS

import { Component, OnInit } from '@angular/core';
import { FormBuilder, FormGroup, FormControl } from '@angular/forms';
import { EMPTY } from 'rxjs';
import { tap, distinctUntilChanged, switchMap, startWith } from 'rxjs/operators';

interface Address {
  street: string;
  city: string;
  country: string;
}

@Component({
  selector: 'my-app',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent implements OnInit {
  public isSameAddressControl: FormControl = new FormControl(false);

  public addresses: FormGroup = this.fb.group({
    sendingAddress: this.fb.group({
      street: '',
      city: '',
      country: ''
    }),
    billingAddress: this.fb.group({
      street: '',
      city: '',
      country: ''
    })
  });

  constructor(private fb: FormBuilder) { }

  ngOnInit() {
    this.isSameAddressControl
      .valueChanges
      .pipe(
        distinctUntilChanged(),
        switchMap(isSameAddress => {
          if (isSameAddress) {
            return this.addresses
              .get('sendingAddress')
              .valueChanges
              .pipe(
                // at the beginning fill the form with the current values
                startWith(this.addresses.get('sendingAddress').value),
                tap(value =>
                  // every time the sending address changes, update the billing address 
                  this.addresses
                    .get('billingAddress')
                    .setValue(value)
                )
              )
          } else {
            this.addresses
              .get('billingAddress')
              .reset();

            return EMPTY;
          }
        })
        // don't forget to unsubscribe when component's destroyed
      )
      .subscribe();
  }
}

HTML

<input type="checkbox" [formControl]="isSameAddressControl"> Same address for sending/billing

<form [formGroup]="addresses">
  <ng-container formGroupName="sendingAddress">
    Sending address<br>
    <input type="text" formControlName="street" placeholder="Street" autocomplete="off"><br>
    <input type="text" formControlName="city" placeholder="City" autocomplete="off"><br>
    <input type="text" formControlName="country" placeholder="Country" autocomplete="off"><br>
  </ng-container>

  <ng-container formGroupName="billingAddress">
    Billing address<br>
    <input type="text" formControlName="street" placeholder="Street" autocomplete="off"><br>
    <input type="text" formControlName="city" placeholder="City" autocomplete="off"><br>
    <input type="text" formControlName="country" placeholder="Country" autocomplete="off"><br>
  </ng-container>
</form>

Here's a working example on Stackblitz: https://stackblitz.com/edit/angular-nyjsnt

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for your guide. How can i use this sample with rxjs 5.5.2. I can't seem to get it to work
Instead of pipe you have to chain the calls for observables (but you should rather upgrade...)
Please can you kindly guide on how to use chain instead of pipe. Thank you
Wondering why somebody just down voted my answer. I'd be glad to get an explanation :)
Excellent answer! However I seem to be getting an error on the switchMap(isSameAddress => { ... line. Error: TS2345: Argument of type '(isSameAddress: any) => Observable<any> | undefined' is not assignable to parameter of type '(value: any, index: number) => ObservableInput<any>'.

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.