Join the Observable and formControl in Angular 4 by subscribing

My goal is to display the data retrieved from FireStore in the screen fields upon loading. However, the buildForm() function is being called before subscribing to the data, resulting in the failure to populate the screen fields with the FireStore data.

perfil-model.ts:

export class Perfil {
    nome: string;
}

authService.ts:

getPerfil() {
    return this.afs.doc<Perfil>(`perfil/${this.id}`)
      .snapshotChanges()
      .map(p => {
        return { ...p.payload.data() };
      });
  }

perfilUser.component.ts:

  perfil: Perfil = new Perfil();
  perfilForm: FormGroup;

  ngOnInit() {
    const subscribe = this.authService
    .getPerfil()
    .subscribe((p: any) => {
      subscribe.unsubscribe();
      this.perfil = p;
    })

    this.buildForm();
  }

  buildForm() {
    this.perfilForm = this.formBuilder.group({
      nome: this.perfil.nome,
    });
  }

perfilUser.component.html:

<form [formGroup]="perfilForm" novalidade>
        <div class="row">
          <div class="form-group col-12 col-sm-12 col-md-7 col-lg-4 col-xl-4">
            <label for="name">Nome*</label>
            <input type="text" class="form-control" formControlName="nome" placeholder="Nome">
          </div>
</form>

Although I've confirmed that FireStore values are being returned, I'm struggling to display them on the screen.

Answer №1

Implement patchValue within the subscribe method

this.authService
    .fetchProfile()
    .subscribe((profile: any) => {
      this.profileForm.patchValue({'name' : profile.name})
    })

Answer №2

To ensure that the observable populates your form, you need to invoke the buildForm method within the subscribe function or alternatively set values within the subscribe function. Below is an illustration of this concept:

perfil.component.ts

nome:string;
constructor(){
    this.perfilForm = new FormGroup({
       "nome": new FormControl(this.nome)
    });
}    

ngOnInit() {
    const sub = this.authService
    .getPerfil()
    .subscribe((p: any) => {
         sub.unsubscribe();
         this.nome = p.nome;
    })
  }

perfil.component.html

<form [formGroup]="perfilForm" novalidade>
    <div class="row">
      <div class="form-group col-12 col-sm-12 col-md-7 col-lg-4 col-xl-4">
        <label for="name">Nome*</label>
        <input type="text" class="form-control" formControlName="nome" placeholder="Nome" [(ngModel)]="nome">
      </div>
    </div>
</form>

Answer №3

Issue with Saving Blank Fields

Error message: When leaving a blank field, it is not saved as an empty string and results in an error.

perfilUser.component.html:

<form [formGroup]="perfilForm" novalidade>
<div class="row">
  <div class="form-group col-12 col-sm-12 col-md-7 col-lg-4 col-xl-4">
    <label for="name">Nome*</label>
    <input type="text" class="form-control" [(ngModel)]="perfil.nome" formControlName="nome" placeholder="Full Name">
  </div>

<button class="btn btn-success" type="button" (click)="saveProfile()">Save</button>

</form>

perfilUser.component.ts:

perfil: Perfil = new Perfil();

  saveProfile() {
    this.authService.createProfile(this.perfilForm.value);
  }

authService.ts:

@Injectable()
export class AuthService {

  perfil: Observable<Perfil[]>;
  userId: string;

  constructor(private afs: AngularFirestore) {
    this.afAuth.auth.onAuthStateChanged((user) => {
      if (user) {
        this.userId = user.uid;
      }
    })
}

createProfile(perfil: Perfil) {
    const userRef: AngularFirestoreDocument<Perfil> = this.afs.doc(`perfil/${perfil.userId}`);
    return userRef.set(perfil);
  }

perfilModel.ts:

export class Perfil {
    nome: string;
    ..... : string;
    ..... : string;
}

the rest of the code is at the beginning of the question

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

I am having trouble accessing the value from an Angular 2 service outside of the subscribe function

Within my component, there is a save function that looks like this: save() { var result; //For updating task if (this.task.AllTaskId) { if (this.task.AssignedToCode == null) { this.task.AssignedToCode = "All"; } ...

Combining Rollup, Typescript, and converting images to base64 during the loading process

Having trouble preloading an image with Rollup. None of the solutions that should work seem to be effective, and I can't figure out why. Has anyone successfully managed to make this work? Here is my configuration in rollup.config.js: import image fr ...

Allow users to zoom in and out on a specific section of the website similar to how it works on Google Maps

I am looking to implement a feature on my website similar to Google Maps. I want the top bar and side bars to remain fixed regardless of scrolling, whether using the normal scroll wheel or CTRL + scroll wheel. However, I would like the central part of the ...

Having trouble getting Laravel and Angular to filter data by categories?

I am currently developing an ecommerce project using Laravel and Angular. I have products and brands associated with these products. In my function to retrieve the products in Laravel, I have used a nullable parameter like this: public function index($bran ...

How to Connect to Printer in Ionic 2

Does anyone know if there is an option to implement printing/connecting a printer from Ionic 2? Is there a Cordova plugin available for printing? I found this plugin: Cordova Print plugin Any help/information on this would be greatly appreciated. Also, i ...

Angular 7 and its scrolling div

Currently, I am working on implementing a straightforward drag and drop feature. When dragging an item, my goal is to scroll the containing div by a specified amount in either direction. To achieve this, I am utilizing Angular Material's CDK drag an ...

Description: TypeScript type that derives from the third constructor parameter of a generic function

How can I determine the type of constructor props for a generic type? Take a look at this example. type PatchableProps<T> = T extends { [k: string | number]: any } ? { [Key in keyof T]: PatchableProps<T[Key]> } : T | Patch export class ...

Having difficulty customizing Mui Accordion with Styled Utility implementation

I am having trouble overriding the CSS for an Accordion using Mui styled utility. I am trying to apply a custom CSS class, but there seems to be an underlying class that is causing issues in my code. Here is the Mui class snippet: <div class="MuiPa ...

Learn how to capture complete stack traces for errors when using Google Cloud Functions

In the codebase I am currently working on, I came across a backend service that I would like to utilize for logging all errors along with their corresponding Http statuses. If possible, I also want to retrieve the full stack trace of these errors from this ...

Is it possible to modify the background-image using Typescript within an Angular project?

I have been struggling to change the background image in my Angular project using Typescript. I attempted to make the change directly in my HTML file because I am unsure how to do it in the CSS. Here is the line of code in my HTML file: <div style="ba ...

Angular service is continuously throwing the error message "NullInjectorError: No provider for anotherService"

I recently built a basic Angular service and encountered an issue. @Injectable() export class someHandler { constructor( public anotherService: anotherService, ) {} ... The problem arises when I try to use this service in a component, as ...

Utilizing event bubbling in Angular: a comprehensive guide

When using Jquery, a single event listener was added to the <ul> element in order to listen for events on the current li by utilizing event bubbling. <ul> <li>a</li> <li>b</li> <li>c</li> <li>d< ...

showing javascript strings on separate lines

I need assistance with displaying an array value in a frontend Angular application. How can I insert spaces between strings and show them on two separate lines? x: any = [] x[{info: "test" + ',' + "tested"}] // Instead of showing test , teste ...

The function getStaticPaths() will generate a 404 error, indicating that the page

I have encountered a persistent issue with the getStaticPaths() function throwing a 404 error. After investigating, I suspect that the problem may lie in the implementation of the getAllPostIds() function, which is supposed to generate an array of object ...

How can I access the ng-template in a component?

How can I reference <ng-template #modal_Template> in my component.ts file? Previously, I triggered a modal using a button on my HTML file and included this code: <button type="button" class="btn btn-primary" (click)="openModal(modal_Template)"> ...

angular - apply custom background styles without resorting to disabling ViewEncapsulation

I can't seem to figure out why I'm struggling to set the background of my component correctly without having to use ViewEncapsulation.None. Currently, with ViewEncapsulation.None, my styles look like this: * { margin: 0; padding: 0; ...

How to Eliminate Lower Borders from DataGrid Component in Material UI (mui)

I've been trying to customize the spacing between rows in a MUI Data Grid Component by overriding the default bottom border, but haven't had much success. I've experimented with different approaches such as using a theme override, adding a c ...

Is it necessary to conceal Angular navigation controls when the user is not authenticated?

In Angular, is there a standardized method for hiding controls when the user is not logged in? We already have the CanActivate guard which checks if a user can access a route. Would it be better to hide the route initially if the user is not logged in or l ...

Accessing data from an API and showcasing information on a chart using Angular

I'm currently developing a dashboard application that requires me to showcase statistics and data extracted from my MongoDB in various types of charts and maps using Angular and Spring Boot. The issue I'm facing is that when attempting to consume ...

Encountering difficulties when attempting to upload a file to Google Cloud Platform using Multer in a Node.js

I am currently experimenting with uploading a single file using Multer and the "multipart/form-data" content type to a Google Cloud Storage bucket. For this task, I am utilizing "Multer.memoryStorage()" and "@google-cloud/storage" try { const docume ...