Using Angular 8 to Pass Form Data to Another Component via a Service

Is there a way to send all the Formgroup data as a Service in Angular to Another Component without using ControlValueAccessor? I want the receiver to automatically receive the value data whenever someone enters information on a form.

I am attempting to modify the code below to achieve this functionality.

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

Answer №1

Here is a suggestion that may be close to what you are looking for in your AddressFormComponent. Make sure to properly manage the subscription as shown 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();
}

This setup will then send data to the specific subject and notify its subscribers accordingly. To verify, you can try the following approach:

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 display the form data received
    });
  }

}

Answer №2

There is no need to manually respond to an event. The FormGroup already comes with an observable that handles the changes.

For example:

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

  ngOnDestroy() {
    // Perform 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() { }
}

If you want to display the form changes in the template, it's recommended to use the async pipe for subscribing only when the data is defined. Here's how you can do it:

// 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>

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Retain the jQuery dropdown menu in an open state while navigating to a different webpage on the

I am encountering an issue with a drop-down menu on my website. Whenever I click on a submenu link, the new page opens but the menu automatically closes. However, I want the active menu to remain open even on the new page. To solve this problem, I believe ...

What is the reason for this interceptor being activated only for the Sent-Event and not for the actual response?

I am dealing with multipart/mixed content from a server that contains JSON and bytes. I need to parse this content into an object in Angular. This is how I make my request: public sendRequest(headerData: string): Observable<MultipartResponse> { ...

Guide to display half of an image and allow for full image viewing upon mouse hover

After creating my bootstrap 4 website, I encountered an issue with the code below where only half of the image is displayed initially due to a conflict in the code. It also fails to work properly when moving the mouse after shifting the whole image from ri ...

Unable to make a reference to this in TypeScript

In my Angular2 application, I have a file upload feature that sends files as byte arrays to a web service. To create the byte array, I am using a FileReader with an onload event. However, I am encountering an issue where I cannot reference my uploadService ...

Implement a CSS style for all upcoming elements

I'm currently developing a Chrome extension tailored for my personal needs. I am looking to implement a CSS rule that will be applied to all elements within a certain class, even if they are dynamically generated after the execution of my extension&ap ...

Refreshing Form in Angular 2

When I remove a form control from my form, it causes the form to always be invalid. However, if I delete a character from another input field and then add the same character back in (to trigger a change event), the form becomes valid as expected. Is ther ...

A guide on implementing a Material UI table to display one row at a time on each page

I'm currently working on incorporating a Material UI table to showcase content with just one row per page. After successfully loading the page and displaying the first row, I encountered an issue where navigating to subsequent pages does not render a ...

Limit the radio button to being clickable

Ugh, I'm really struggling with this. I want to create a quiz where only the radio button is clickable, not the text itself. Can anyone help me figure out how to do this? I have two codes below that I don't quite understand. I'll include th ...

Struggling with the conundrum of aligning a constantly changing element amid the

I was optimistic about the code I wrote, hoping it would work out in the end. However, it seems that my expectations might not be met. Allow me to provide some context before I pose my question. The animation I have created involves an SVG element resembl ...

Central Player Component

Do you need help with centering text and a player on your WP site? Check out my website Here is the code I am currently using: <div class="listen_section"> <div class="container"> <div class="row"> <div class ...

I am interested in updating the color of the active item on the navbar

I am looking to modify the color of the active page, Here is the HTML code snippet: <html> <head> <title>John Doe - Portfolio</title> <link rel="stylesheet" href="custom-style.css"> <link rel=" ...

"Unlock the secrets to commanding respect in the web form layout by mastering the art

I have a fieldset that includes a legend with potentially long text content. I need the legend to only take up 50% of the width of the fieldset. Currently, when the legend is too lengthy, it still occupies 50% of the space but causes the entire fieldset ...

Transitioning from MVC to Angular 2 and TypeScript: A Step-by-Step Guide

Seeking guidance as I venture into the world of Angular. My goal is to pass a string variable 'element' to my UI and utilize it. However, I am unsure about how to go about passing it inside main.js and beyond. How can I transfer a variable to a t ...

What causes the cancel button to add spaces and create a line break in the textarea field?

Whenever I click the "cancel" button, the textarea inexplicably receives 26 spaces before any existing text and a carriage return after it. This issue occurs when the cancel button is styled in the traditional HTML manner: <button type="reset" name="re ...

What steps should I take to fix an error in my code?

My current objective is to write a program that generates a square with dimensions of 200 pixels by 200 pixels. The square should be colored using specific RGB values: red (red value of 255), green (green value of 255), blue (blue value of 255), and magent ...

Issue with using variables in nodejs, express, and EJS: Undefined

Having some trouble with EJS here. I am using response.render('agent.html', {name: 'aaaa'});, and in my HTML script, I attempt to access <%= this.name %>. Unfortunately, I keep getting a ReferenceError: aaaa is not defined. Any sugge ...

Invoking Angular component method using vanilla JavaScript

For my web application, I am utilizing Angular and require Bluetooth functionality on a specific page. I am implementing loginov-rocks/bluetooth-terminal (https://github.com/loginov-rocks/bluetooth-terminal) for establishing the Bluetooth connection, which ...

Utilize the display property with grid to effortlessly expand a block to occupy the entire width

I am currently exploring the grid system and I have a specific challenge. I would like the third block to expand to its full width without the need for extra classes. Can this be achieved using only internal CSS? .grid { margin: 36px auto; height: ...

Is concealing content using Javascript or jQuery worth exploring?

While I have been hiding content using display:none; in css, there are concerns that Google may not like this approach. However, due to the needs of jQuery animations, it has been necessary for me. Recently, I have come across a new method for hiding conte ...

The issue with displaying inline block is that the divs are not appearing side by side on the

Two of my div elements, namely form-panel and data-panel, are currently not aligned on the same line. How can I use display:inline-block to align them in a single line? Please review the code provided below. I have already used display:inline-block on both ...