Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Angular 2 Updating Component After Form Submit With New Data From Response

Tags:

angular

Background

On page load I am making a http get call to obtain some data.

There is a form on the page which submits new data to the APi. The response does not hold the new updated data but the data exist in the database after the form is submitted.

I need to access the data by making a second api call after the form is submitted.

Question

After the form is submitted, how do I make the initial API call again to retrieve current data and then update my view component with it?

Code

On page load I call this function inside

Initial call to retrieve data

ngOnInit() { this.getPaymentMethods() }

Function definition

private getPaymentMethods() {
            let params: URLSearchParams = new URLSearchParams();
            params.set('api_key', this.apiKeyData);
            params.set('email', this.auth.user.email);
            return this.http.get(STATICS.API_BASE + STATICS.API_ALL_PAYMENT_METHODS,
                { search: params })
                .map((res: Response) => res.json()).subscribe((res) => {
                    localStorage.setItem('payment_profiles', JSON.stringify(res.payment_profiles));
                });
        }

Handling Response From Initial Call

Parsing the data object response

this.PaymentMethodKeys = Object.keys(this.pMethodsData);

Inside the view I display the data like this

<div *ngFor="let key of PaymentMethodKeys">
{{pMethodsData[key].card_no}}
{{pMethodsData[key].payment_profile_id}}
</div>

This is the form that is submitted to add new data to database

    saveCreditCard(model: Payment, isValid: boolean) {
            let params: URLSearchParams = new URLSearchParams();
            params.set('api_key', this.apiKeyData);
            params.set('email', model.email);

   params.set('u_address', model.street_address);
            params.set('u_city', model.city_address);

            return this.http.get(STATICS.API_BASE + STATICS.API_PAY_METHOD,
                { search: params })
                .map((res: Response) => res.json())
                .subscribe((res) => {
                    console.log(res);
                });
        }
    }

I think part of my problem is that I am getting the keys from the object inside the constructor. So I think I keep trying to make this work but the only way it will update the keys is when the component refreshes so the constructor will run again.

Any help would be appreciated.

like image 858
wuno Avatar asked Oct 30 '22 11:10

wuno


1 Answers

We discussed Subjects, but that's not necessary. It's sufficient to render the observable in the view and simply pass it new data each time you update your database.

import { Observable } from 'rxjs/Observable';
import 'rxjs/add/operator/take';

private paymentMethods: Observable<any>;

private getPaymentMethods() { 
    let params: URLSearchParams = new URLSearchParams(); 
    params.set('api_key', this.apiKeyData); 
    params.set('email', this.auth.user.email); 
    this.http.get(STATICS.API_BASE + STATICS.API_ALL_PAYMENT_METHODS, 
    { search: params }) 
    .map((res: Response) => res.json()) 
    .take(1) //Takes the first observable and unsubscribes
    .subscribe(res => this.paymentMethods = res.payment_profiles)
}

saveCreditCard(model: Payment, isValid: boolean) {
    let params: URLSearchParams = new URLSearchParams();
    params.set('api_key', this.apiKeyData);
    params.set('email', model.email);

    return this.http.get(STATICS.API_BASE + STATICS.API_PAY_METHOD,{ search: params }) 
    .map((res: Response) => res.json())
    .take(1)
    .subscribe((res) => {
        //Maybe make sure status is 200. 
        console.log(res); 
        this.getPaymentMethods(); 
    });
}

ngOnInit() { 
    this.getPaymentMethods()
}

Note that since we are subscribing to the results of getPaymentMethods() within the function, it's not necessary for it to return anything and, hence, not necessary for us to assign the returned Observable to paymentMethods within ngOnInit(). Whenever getPaymentMethods() is called (e.g., on the initial load and when saveCreditCard() is called) paymentMethods subscribes to the first response emitted and then unsubscribes with the take operator.

And in your view you'll notice we aren't using the async pipe anymore. Remember that the async pipe subscribes and unsubscribes. We are doing that manually, so there's no need for that.

<div *ngFor="let item of paymentMethods">
    {{item.card_no}}
</div>

Let me know how this works out.

like image 65
J. Adam Connor Avatar answered Nov 11 '22 13:11

J. Adam Connor