1

I have a angular 2 app and I'm using route to navigate between the component. To pass the data between the sibling component I'm using Observable and Subscription pattern. But how to send data with routing(I need to pass object)

app.component.ts

@Component({
 providers: [DataShareService]
})
....

app.component.html

<router-outlet></router-outlet>

DataShareService

 export class DataShareService {
    // Observable string sources
    private dataSource = new Subject<any>();
    private createdPostSource = new Subject<any>();

    // Observable string streams
    dataSource$ = this.dataSource.asObservable();
    createdPostSource$ = this.createdPostSource.asObservable();
    // Service message commands
    passData(data: any) {
     this.dataSource.next(data);
    }

    passCreatedPostSource(data:IPost[]){
     this.createdPostSource.next(data);
    }

  }

PostListComponent

@Component({
  selector: 'app-post-list',
  templateUrl: './post-list.component.html',
  styleUrls: ['./post-list.component.css']
})
export class PostListComponent implements OnInit {

  private _postUrl: string;
  public posts: IPostList;
  public createPost: string;
  private dataSub: Subscription;

  constructor(private _postService: PostService,
              private _config: ConfigService,
              private  _logger: ErrorLogService,
              private _dataShareService: DataShareService,
              private _router: Router) {
  }


  ngOnInit(): void {
    this._postUrl = this._config.get('postApiRoot');

    this._postService.getPosts(this._postUrl)
      .subscribe(
        result => this.posts = result,
        error => this._logger.logError(error)
      );
    this.dataSub = this._dataShareService.createdPostSource$
      .subscribe(post => {
        this.posts.result.unshift(post);
        console.log(this.posts.result);
      });
  }

  createResponse(post): void {
    this._dataShareService.passData(post);
    console.log("postlist:" + post);
  }

  ngOnDestroy(): void {
    this.dataSub.unsubscribe();
  }
}

link in html

 <a [routerLink]="['/post',post.id]" (click)="createResponse(post)">{{post.title}}</a>

post-detail.component.ts

@Component({
  selector: 'app-post-detail',
  templateUrl: './post-detail.component.html',
  styleUrls: ['./post-detail.component.css']
})
export class PostDetailComponent implements OnInit {

  private _postDetailPath: string;
  private dataSub: Subscription;
  private _post: IPost;

  constructor(private _router: Router,
              private _route: ActivatedRoute,
              private _config: ConfigService,
              private _dataShareService: DataShareService,
              private _logger: ErrorLogService) {

  }

  ngOnInit() {
    this.dataSub = this._dataShareService.dataSource$.subscribe(
      post => {
        this._post = post;
        console.log('post : ' + this._post);
      }, error => {
        console.log('errr0');
        this._logger.logError(error);
      },() => {console.log('post : error' )});

  }

  onBack(): void {
    this._router.navigate(['/posts'])
  }
  ngOnDestroy() {
    this.dataSub.unsubscribe();
  }

}

unable to get the data in ngOnInit() of post-detail after redirect.

How does this works? If i don't you routing its works. but how to made it work with routing?

Akkusativobjekt
  • 2,005
  • 1
  • 21
  • 26
Dinkar Thakur
  • 3,025
  • 5
  • 23
  • 35
  • I am facing a similar issue. I have a common RouterService defined which is used by all the components for routings. Now I have integrated AutGuard which passes boolean observable from the SharedService - I am facing issue to import DataSharingService in RoutinService. Not sure what the issue is. – Kushal Jayswal Dec 06 '19 at 10:31

2 Answers2

0

The service must be loaded by a module that loads the 2 components or a module that loads the two modules where the components are declared so you will have a singleton instance of the service and can share data between the two components.

In your case, remove the service from component providers and put it in the app.module providers. This way you will have a singleton and the data can be shared.

Bruno João
  • 5,105
  • 2
  • 21
  • 26
  • i did the change you told me to do,and changes ngOnInit to this.dataSub = this.dataShareService.dataSource$.subscribe(post => { console.log(post); }); to test but nothing got logged – Dinkar Thakur Jan 20 '17 at 13:26
  • its seems .subscribe is never getting fired – Dinkar Thakur Jan 20 '17 at 13:29
  • I think you still having two instances of the service. Can you provide a plunker to us so we can see the entire code? Like, who declares the two components? Where are the service provided, in which modules? – Bruno João Jan 20 '17 at 13:31
  • now its not working first time. if i refresh the listing page and click in detail it doesn't work. but if i hit back button and click on another list item link it starts working till i refresh the app. – Dinkar Thakur Jan 20 '17 at 13:38
  • I've got the exact same problem when using routing, and if I click around on different components eventually the subscription fires. Did you ever fix your issue? – Jason Simpson May 31 '17 at 08:40
0

Just fixed mine based on the post here. You just replace

new Subject<any>();

with

new BehaviorSubject(undefined);

And then you might have to deal with the undefined somewhere depending on how you're using it. I know that seem hacky but it works.

Jason Simpson
  • 4,653
  • 5
  • 16
  • 26