Проблема Angular 4/5 с темой маршрутизации между компонентами Angular через Angular Services

У меня есть родительский компонент с событием щелчка HTML, который передает элемент clicked методу в файле component.ts. Я бы хотел, чтобы это событие щелчка было перенаправлено в службы, превращено в новый Subjectзатем с помощью next() метод, передайте тему для другого компонента Sibling и свяжите данные с HTML компонента Sibling.

Таким образом, маршрутизация этих данных будет выглядеть так:

Родительский компонент (через событие щелчка) -> Сервис (через метод родительского компонента) -> Братский компонент (через Сервис)*

Здесь начинается передача данных:

app.component.ts

import { Component, OnInit } from '@angular/core';
import { Router } from '@angular/router';
import { ApiService } from '../api.service';

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

  sortedFavorites: any[] = [];
  sortedContacts: any[] = [];

  constructor (private _apiService: ApiService, private router: Router) {}

  ngOnInit(){ this.getContacts()}

  getContacts() {
     this._apiService.getContacts()
     .subscribe(
       (contacts) => {

        //Sort JSON Object Alphabetically
        contacts.sort( (a, b) => {
          if (a.name > b.name) return 1;
          if (a.name < b.name) return -1;
          return 0;
        });

         //Build new Sorted Arrays
          contacts.forEach( (item) => {
           if (item.isFavorite) {
           this.sortedFavorites.push(item);
           } else {
           this.sortedContacts.push(item);
           }
         });
       });
     }

  openFavorite($event, i) {<--HTML click event passing 'i' in as object clicked
    let selectedFavorite = this.sortedFavorites[i];
      this._apiService.openSelectedContact(selectedFavorite); <--passing said object into method connected to my services.ts file 
      this.router.navigate(['/details']);
  };

}

Данные, которые я передаю вместе с openFavorite() Метод, который я создал, работает, потому что делает console.log(selectedFavorite) регистрирует желаемый результат для передачи.

Тогда это переходит к услугам

app.service.ts:

import { Injectable } from '@angular/core';
import { Http, Response } from '@angular/http';
import { Observable } from 'rxjs/Observable';
import { Subject } from 'rxjs/Subject';
import 'rxjs/add/operator/map';

@Injectable()
export class ApiService {

  //API URL
  private url: string = 'assets/api/contacts.json';

  //Create new Subject and assign to local variable
  public newContactSubject = new Subject<any>();

  //Initialize HttpClient for request
  constructor(private _http: Http) { }

  //Pull JSON data from REST API
  getContacts(): Observable<any> {
    return this._http.get(this.url)
    .map((response: Response) => response.json());
  }


  openSelectedContact(data) {
  this.newContactSubject.next(data); <---Where data should be passing in!

  }
}

** Теперь я хотел бы, чтобы мой другой компонент получал данные из app.service.

import { Component, OnInit } from '@angular/core';
import { ContactsListComponent } from './app/contacts-list/contacts-list.component';
import { ApiService } from '../api.service';

@Component({
  selector: 'app-contact-details',
  templateUrl: './contact-details.component.html',
  styleUrls: ['./contact-details.component.scss']
})
export class ContactDetailsComponent implements OnInit {

  selectedContact: any[] = [];

  error: string;

  constructor(private _apiService: ApiService) { }

  ngOnInit() { this.showContact() }

  showContact() {
  this._apiService.newContactSubject.subscribe(
    data => this.selectedContact = data)  <--Where the data should be showing up from services.ts file
    console.log(this.selectedContact.name);  <-- This is logging Undefined
  }
}

Что бы мне здесь не хватало? Большое спасибо заранее!

2 ответа

Решение

Попробуй это:

showContact() {
  this._apiService.newContactSubject.subscribe(
    data => {
       this.selectedContact = data;
       console.log(this.selectedContact.name);
    }
}

Обе строки кода (включая вашу регистрацию) находятся внутри функции, передаваемой в подписку. Каждый раз, когда элемент отправляется, он запускает код только в функции обратного вызова.

И как примечание... обычно рекомендуется, чтобы вы делали свой предмет частным и выставляли его только для чтения, наблюдаемого с помощью кода примерно так:

private selectedMovieSource = new Subject<IMovie | null>();
selectedMovieChanges$ = this.selectedMovieSource.asObservable();

Обратите внимание, что субъект является частным, и его можно наблюдать, используя отдельное свойство. Затем компоненты подписываются на общедоступную заметку субъекта.

Во -первых, метод сортировки вашего компонента никогда не будет сортироваться, потому что вы игнорируете возвращаемое значение. Если вы хотите разобраться с сортировкой, используйте следующее concatcts = contacts.sort(...)

и я предлагаю вам другой шаблон:

import { Component, OnInit } from '@angular/core';
import { ContactsListComponent } from './app/contacts-list/contacts-list.component';
import { ApiService } from '../api.service';
import { OnDestroy } from "@angular/core";
import { ISubscription } from "rxjs/Subscription";

@Component({
    selector: 'app-contact-details',
    templateUrl: './contact-details.component.html',
    styleUrls: ['./contact-details.component.scss']
})
export class ContactDetailsComponent implements OnInit, OnDestroy {

    selectedContact: any[] = [];

    error: string;
    private subscription: ISubscription;

    constructor(private _apiService: ApiService) { }

    ngOnInit() { 
      this.subscription = this._apiService.newContactSubject().subscribe(data => {
        this.selectedContact = data;
        console.log(this.selectedContact.name);
      });
    }

    showContact() {
      this._apiService.newContactSubject.subscribe();
    }

    ngOnDestroy() {
      this.subscription.unsubscribe();
    }
}

Но я обнаружил, что есть еще одна проблема: вы определили selectedContact как любой объектный массив, тогда вы хотите достичь значения как объекта: this.selectedContact.name Я надеюсь, что вы можете решить эту проблему:)

Другие вопросы по тегам