Angular 5+ Sibling Component Communication Using RxJS (Subject)

落爺英雄遲暮 提交于 2019-12-24 10:29:40

问题


My app has listing of tiles that when clicked on will display in a dashboard. In the dashboard, when a tile is clicked, the tile details show below the dashboard (not unlike tour-of-heroes).

I’m using RxJS Subject in a service to communicate successfully between Component A (available snippets), Component B (the dashboard), and the Component C (snippet details).

The problem is that when I click on the one of the listings on component A, not only does it populate the dashboard like it should but also populates the details (Component C). I only want the details to be populated when the tile is clicked on in the dashboard - yes, the details do successfully populate when a dashboard tile is clicked.

All 3 components are siblings residing in app.component.html. I do not want parent-child relationships - hence using Subject instead of @Inupt.

The service:

@Injectable()
export class SnippetService {

  tile  = new Subject<any>();

  constructor() { }

  getSnippets(): Observable<Snippet[]> {
    return of (SNIPPETS);
  }

  addTile(data) {
    this.tile.next(data);
  }

}

Component A (available tiles/snippets):

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

  snippets: Snippet[];

  constructor(private snippetService: SnippetService) { }

  ngOnInit() {
    this.getSnippets();
  }

  getSnippets(): void {
    this.snippetService.getSnippets().subscribe(x => this.snippets = x);
  }

  onAddTile(data) {
    this.snippetService.addTile(data);
  }

}

Component B (The dashboard):

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

  selectedSnippet: Snippet;

  addedSnippets = [];

  // Inject the SnippetService
  constructor(private snippetService: SnippetService) { }

  ngOnInit() {
    this.snippetService.tile.subscribe(x => this.addToDashboard(x));
  }

  addToDashboard(s: Snippet) {
    if (this.addedSnippets.indexOf(s) === -1) {
      this.addedSnippets.push(s);
    }
  }

  displayDetails(s: Snippet) {
    this.snippetService.addTile(s);
  }

}

Component C (snippet details)

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

  snippet: Snippet;

  constructor(private snippetService: SnippetService) { }

  ngOnInit() {
   this.snippetService.tile.subscribe(x => this.snippet = x);
  }

}

Component C Template:

<div class="snippet-detail" *ngIf="snippet">
  <hr>
  <h2>{{ snippet.title }} </h2>
  <div>{{snippet.description}}</div>
  <code>{{snippet.code.example1}}</code>
  <code>{{snippet.code.example2}}</code>
  <code>{{snippet.code.example3}}</code>
</div>

So the the culprit is between the ngOnInit{} in Component C and the *ngIf="snippet" on C's view. I tried passing additional booleans from the service but the problem is that I need the state of those bools to be in a lifecycle loop.

So a RxJS'y way of doing this?


回答1:


The service:

@Injectable()
export class SnippetService {

  tile  = new Subject<any>();
  details  = new Subject<any>();

  constructor() { }

  getSnippets(): Observable<Snippet[]> {
    return of (SNIPPETS);
  }

  addTile(data) {
    this.tile.next(data);
  }

  showDetails(data) {
    this.details.next(data);
  }

}

Component B (Dashboard) now passes the snippet to the snippet.service showDetails() method:

  displayDetails(s: Snippet) {
    this.snippetService.showDetails(s);
  }

Component C (details) now subscribes to the details subject and assigns the result to C's snippet property:

 ngOnInit() {
   this.snippetService.details.subscribe(x => this.snippet = x);
  }


来源:https://stackoverflow.com/questions/49889376/angular-5-sibling-component-communication-using-rxjs-subject

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!