0

I'm new to Angular2. I've been learning what I have mainly though the official docs, a slightly outdated udemy course by Mosh, and a book called ng-book2.

What I have is a form that always exists on the (top of the) page. Underneath it is a listing from the database. Clicking an item from the listing replaces the entire listing with details of that item. Clicking the back button takes you back to the listing. The form remains on top. It's a basic CRUD application. Submitting the form saves a new item to the database.

The problem is when I submit the form, the listing does not automatically get the new item: instead I have to refresh the page. Other operations (upvote, downvote, delete) are working fine.

app.component.html:

<app-article-form [listid]="listid" [formid]="formid"></app-article-form>
<router-outlet></router-outlet>

The router outlet displays either the item listing or an item detail.

Program architecture: I have a separate component for the form (ArticleFormComponent), a separate component for the listing (ArticlesComponent) and a separate component for detail (ArticleDetailComponent). Routing is between ArticlesComponent and ArticleDetailComponent.

I basically want ArticleFormComponent to notify it's sibling ArticlesComponent that a new Article has been submitted, and I want ArticlesComponent to receive that Article and push() it in the Articles[] array.

I googled a bit and tried to implement an emitter service to broadcast the event but the problem is that I'm using a router-outlet and do not know how to set input properties in that. Could someone guide me in the right direction? Thanks.

  • if I understand you correctly, this is what you want: https://angular.io/docs/ts/latest/cookbook/component-communication.html#!#bidirectional-service It shows how to notify a component via a Subscription on a Observable from a Service. – Korgen Dec 10 '16 at 21:44

1 Answers1

1

You could for example implement a PubSub pattern using simply RxJS's ReplySubject class. Here is how:

import { Injectable } from '@angular/core';
import { ReplaySubject } from 'rxjs';

@Injectable()
export class ArticlesPubSubService extends ReplaySubject<IArticle> {

  constructor() {
    super();
  }

}

Then use this ArticlesPubSubService in both components:

1) in articles-form.component.ts you would emit the new created article:

import { Component, OnInit } from '@angular/core';
import { ArticlesPubSubService } from '../articles-pub-sub.service';

@Component({
  selector: 'so-articles-form',
  templateUrl: './articles-form.component.html',
  styleUrls: ['./articles-form.component.css']
})
export class ArticlesFormComponent implements OnInit {

  constructor(private aps: ArticlesPubSubService) { }

  ngOnInit() {
  }

  submit(article) {
    // ... 
    this.aps.next(article);
  }

}

2) In articles.component.ts you would get this new article and push it to your local articles list:

import { Component, OnInit } from '@angular/core';
import { ArticlesPubSubService } from '../articles-pub-sub.service';

@Component({
  selector: 'so-articles',
  templateUrl: './articles.component.html',
  styleUrls: ['./articles.component.css']
})
export class ArticlesComponent implements OnInit {

  articles: IArticles[];

  constructor(private aps: ArticlesPubSubService) { }

  ngOnInit() {
    this.aps.subscribe( article => this.articles.push(article) );
  }
  ngOnDestroy() {
    this.aps.unsubscribe();
  }
}
Wassim Chegham
  • 550
  • 4
  • 15
  • Hi Wassim, thanks very much! this works. I have a question though. In articles.component.ts, the line of code in ngOnInit() now runs every time the component is loaded, whether there is a new article to be added or not. I wanted your opinion as to whether that is a good intended practice in production apps, or whether we should approach in other ways. Thanks! – user3233029 Dec 11 '16 at 09:54
  • the subscription is called each time a new instance of ArticlesComponent is created. Which is what happens when you switch views. For this specific example, you could move the subscribe call to the constructor. it doesn't matter. We're basically telling the component to react **IF** there is an article to be added to the list. So that's fine. If you wanna avoid any potential memory leaks, call unsubscribe() in ngOnDestroy. (I'll update my example). – Wassim Chegham Dec 11 '16 at 13:42