1

I'd like to know the correct approach, how to update data-array after http post.

What I have is a transaction service with those methods:

getUserTransactions(user_id) {
    return this.http.get('http://localhost:3000/users/' + user_id + '/transactions', { headers: contentHeaders })
      .map(res => res.json());
  }

createTransaction(balance, amount, user_id, paymethod_id, redirect) {
    let body = JSON.stringify({ balance, amount, user_id, paymethod_id });
    this.http.post('http://localhost:3000/transactions', body, { headers: contentHeaders })
      .subscribe(
      response => {
        this.router.parent.navigateByUrl(redirect);
      },
      error => {
        alert(error.text());
        console.log(error.text());
      }
      );

and a component

export class HomeComponent {

  public transactions: Transaction[];

  constructor(
    private router: Router,
    private loginService: LoginService,
    private trnService: TransactionService
    ) {
    if (!loginService.isLoggedIn())
      this.router.parent.navigateByUrl('/logout');

    var userid = this.loginService.getUserId();
    this.trnService.getUserTransactions(userid).subscribe(transactions => this.transactions = transactions);

    return;
  }

  makeTransaction(){
    var userid = this.loginService.getUserId();
    this.trnService.createTransaction(10, 2, userid, 1, "/home");
  }

}

html:

<tbody>
    <tr *ngFor="#transaction of transactions; #index=index">
---

So first, by navigating to "/home" I am loading an array of user transactions.

by clicking a button, the makeTransaction() method is called. which executes a http post request by the service TransactionService -> createTransaction. I thought I would redirect to "/home" after transaction is successfully done, but this does not work.. ( I assume that the constructor is not called again.) may be I could update the public transactions: Transaction[]; from the service somehow? Maybe making a reference?

4
  • What do you exactly mean by "this does not work"? Commented Mar 29, 2016 at 10:25
  • the array is not reloaded, only if I would reload the page completely in browser.. I assume that the constructor is not called again. Commented Mar 29, 2016 at 10:30
  • are you sure thhat they are created? Commented Mar 29, 2016 at 10:31
  • yes... if I reload the page, I see results.... Commented Mar 29, 2016 at 10:31

1 Answer 1

1

If you want to see the new transactions in the list of all transactions. You coud leverage a shared service that contains both the list and an observable to notify when a new transaction completed.

As a matter of fact, the transactions list in the component isn't linked to the "create transaction" calls.

Here is a sample implementation:

export class TransactionService {
  private transactionObservable:Observable<any>;
  private transactionObserver:Observer<any>;

  constructor() {
    this.transactionObservable((observer:Observer) => {
      this.transactionObserver = observer;
    }).share();
  }

  notifyTransactionCreated(transaction:any) {
    this.transactionObserver.next(transaction);
  }

  onTransactionCreated(callback:(transaction:any) => void) {
    this.transactionObservable.subscribe(callback);
  }

  (...)

createTransaction(balance, amount, user_id, paymethod_id, redirect) {
  let body = JSON.stringify({ balance, amount, user_id, paymethod_id });
  this.http.post('http://localhost:3000/transactions', body, { headers: contentHeaders })
    .subscribe(
      response => {
        this.notifyTransactionCreated(response.json()); // <------
        this.router.parent.navigateByUrl(redirect);
      },
      error => {
        alert(error.text());
        console.log(error.text());
      }
     );
   }
}

This way you can be notified within the component and update the transaction list:

export class HomeComponent {
  public transactions: Transaction[];

  constructor(
    private router: Router,
    private loginService: LoginService,
    private trnService: TransactionService
  ) {
    if (!loginService.isLoggedIn())
      this.router.parent.navigateByUrl('/logout');

    var userid = this.loginService.getUserId();
    this.trnService.getUserTransactions(userid).subscribe(transactions => {
      this.transactions = transactions;
    });

    this.trnService.onTransactionCreated(transaction => {
      this.transactions.push(transaction);
    });

    return;
  }

  makeTransaction(){
    var userid = this.loginService.getUserId();
    this.trnService.createTransaction(10, 2, userid, 1, "/home");
  }
}

To share a single instance of the service for the whole application, don't forget to specify the service when bootstrapping your application:

bootstrap(AppComponent, [
  HTTP_PROVIDERS,
  TransactionService
]);
Sign up to request clarification or add additional context in comments.

2 Comments

Thanks.. I got it.. General question: my other idea was to pass a reference to the Model into the Service, and then call a method on that Model( that would update transactions list again) is it possible to pass references to components/objects into services somehow?
Yes, you could do something like that. That being said, the observable-based approach is in general better since you can react on changes with your component. See this question: stackoverflow.com/questions/34376854/….

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.