user12250118
user12250118

Reputation:

Angular 8: Send Form data as a Service to Another Component

How do I sent all the Formgroup data as a Service in Angular to Another Component? I am looking for alternative to ControlValueAccessor. So anytime someone writes something on a form, the receiver will get the value data.

Trying to edit the code below to work.

Address Sender Form:

export class AddressFormComponent implements OnInit {

  editAddressForm: FormGroup;

  constructor(private formBuilder: FormBuilder) {

    this.editAddressForm = this.formBuilder.group({
      'streetName' : [null, Validators.required, Validators.maxLength(64)],
      'city' : [null, Validators.required, Validators.maxLength(32)],
      'state' : [null, Validators.required, Validators.maxLength(16)],
      'postalCode' : [null, Validators.required, Validators.maxLength(16)]
    });
  }

  ngOnInit() {
  }

   // What should I write as Event Code??
}

Service:

export class AddressService {

  private messageSource = new Subject();
  currentMessage = this.messageSource.asObservable();

  constructor() { }

  changeMessage(currentMessage) {
    this.messageSource.next(currentMessage);
  }
}

Receiver:

export class AddressCombinedReceiverComponent implements OnInit {

  message: any;

  constructor(private readonly addressService: AddressService) {
    this.addressService.currentMessage.subscribe(currentMessage => this.message = currentMessage);
    }

  ngOnInit() {
  }

}

Related question: Angular 2 - formControlName inside component

Upvotes: 1

Views: 4392

Answers (2)

christian
christian

Reputation: 1705

You don't need to respond to an event. FormGroups already have an observable that streams the changes.

Example

// address-form.component.ts
export class AppComponent implements OnDestroy {
  editAddressForm: FormGroup;

  ngOnDestroy() {
    // cleanup
    this.addressService.formValues$ = null;
  }

  constructor(private addressService: AddressService) {
    this.editAddressForm = new FormGroup({
      streetName: new FormControl(null, { validators: [Validators.required, Validators.maxLength(64)]}),
      city: new FormControl(null, { validators: [Validators.required, Validators.maxLength(32)]}),
      state: new FormControl(null, { validators: [Validators.required, Validators.maxLength(16)]}),
      postalCode: new FormControl(null, { validators: [Validators.required, Validators.maxLength(16)]}),
    });

    this.addressService.formValues$ = this.editAddressForm.valueChanges;
  }
}
// address.service.ts
export class AddressService {
  formValues$: Observable<any>;

  constructor() { }
}

In regards to the receiver, if the intention is to show the form changes in the template, then I recommend using the async pipe for that, so that you only subscribe when it's defined, like:

// address-combined-receiver.component.ts
export class SimpleComponent implements OnInit {
  addressValues$: Observable<any>;

  constructor(private addressService: AddressService) {
    this.addressValues$ = this.addressService.formValues$;
  }

  ngOnInit() {
  }
}

<!-- address-combined-receiver.component.html -->
<ng-container *ngIf="addressValues$ | async as addressValues">
  <pre>{{ addressValues | json }}</pre>
</ng-container>

Upvotes: 1

dev-dan
dev-dan

Reputation: 6283

This doesnt look far away from what you need, in your AddressFormComponent try the following. Ensure to clean up the subscription when needed, added below.

public subs = new Subscription();
public editAddressForm: FormGroup;

constructor(addressService: AddressService){}

public ngOnInit(): void {

  this.editAddressForm = this.formBuilder.group({
    'streetName' : [null, Validators.required, Validators.maxLength(64)],
    'city' : [null, Validators.required, Validators.maxLength(32)],
    'state' : [null, Validators.required, Validators.maxLength(16)],
    'postalCode' : [null, Validators.required, Validators.maxLength(16)]
  });

  this.subs.add(this.editAddressForm.valueChanges.subscribe(data => 
  {
    this.addressService.changeMessage(this.editAddressForm);
  }));
}

public ngOnDestroy(): void
{
  this.subs.unsubscribe();
}

That should in turn push the data to the subject you have an in turn cause the subscribers of that subject to receive the data. To confirm try the following

export class AddressCombinedReceiverComponent implements OnInit {

  public message: any;

  constructor(private readonly addressService: AddressService) {}

  public ngOnInit() {
    this.addressService.currentMessage.subscribe(currentMessage => { 
      this.message = currentMessage;
      console.log(this.message); // should be the form coming through
    });
  }

}

Upvotes: 1

Related Questions