Angular 4 - 将对象从一个组件传递到另一个组件(没有父 - 子层次结构)

Den*_*isN 7 angular-components angular angular-router

我的情况:

我有一个组件显示tile,每个tile表示一个数组中的对象,该数组通过ngfor循环.单击一个图块时,我想将该对象传递给另一个组件,该组件负责在可以修改的字段中显示该对象的所有属性.

我尝试过的:

在做了一些研究并发现多个帖子向我展示了如何为父子层次结构实现这一点以及一些帖子解释为了实现想要的功能需要使用共享服务,我决定尝试设置这样的服务.

然而,我似乎没有得到的是当我应该导航到不同的路线.似乎导航在早期找到了位置,因为在详细信息组件中检索它时,传递给服务的对象是未定义的.

我的代码:

显示切片的组件具有以下功能,可将单击的对象传递给共享服务:

editPropertyDetails(property: Property) {
    console.log('Edit property called');

    return new Promise(resolve => {
      this.sharedPropertyService.setPropertyToDisplay(property);
      resolve();
    }).then(
      () => this.router.navigate(['/properties/detail'])
    )
  }
Run Code Online (Sandbox Code Playgroud)

共享服务具有设置属性对象的功能和检索它的功能,如下所示:

@Injectable()
export class SharedPropertyService {
  // Observable
  public propertyToDisplay = new Subject<Property>();

  constructor( private router: Router) {}

  setPropertyToDisplay(property: Property) {
    console.log('setPropertyToDisplay called');
    this.propertyToDisplay.next(property);
  }

  getPropertyToDisplay(): Observable<Property> {
    console.log('getPropertyToDisplay called');
    return this.propertyToDisplay.asObservable();
  }
}
Run Code Online (Sandbox Code Playgroud)

最后是必须接收被单击的对象但获取未定义对象的detail组件:

export class PropertyDetailComponent implements OnDestroy {

  property: Property;
  subscription: Subscription;

  constructor(private sharedPropertyService: SharedPropertyService) {
        this.subscription = this.sharedPropertyService.getPropertyToDisplay()
          .subscribe(
            property => { this.property = property; console.log('Detail Component: ' + property.description);}
          );
  }

  ngOnDestroy() {
    // When view destroyed, clear the subscription to prevent memory leaks
    this.subscription.unsubscribe();
  }
}
Run Code Online (Sandbox Code Playgroud)

提前致谢!

Den*_*isN 5

我通过传递被单击的图块对象的id来解决该问题,如在路线的导航额外内容中所述,然后在detail组件中使用服务根据通过路线的id来获取对象。

我将在下面提供代码,因此希望没有人再经历所有这些。

显示可单击以查看其包含的对象的详细信息的图块的组件:

  editPropertyDetails(property: Property) {
    console.log('Edit property called');

    let navigationExtras: NavigationExtras = {
            queryParams: {
                "property_id": property.id
            }
        };

    this.router.navigate(['/properties/detail'], navigationExtras);
  }
Run Code Online (Sandbox Code Playgroud)

接收单击对象的详细信息组件

  private sub: any;
  propertyToDisplay: Property;

  constructor
  (
    private sharedPropertyService: SharedPropertyService,
    private router: Router,
    private route: ActivatedRoute
  ) {}

  ngOnInit() {
  this.sub = this.route.queryParams.subscribe(params => {
        let id = params["property_id"];

        if(id) {
          this.getPropertyToDisplay(id);
        }

    });
  }

  getPropertyToDisplay(id: number) {
    this.sharedPropertyService.getPropertyToDisplay(id).subscribe(
            property => {
              this.propertyToDisplay = property;
            },
            error => console.log('Something went wrong'));
  }

  // Prevent memory leaks
  ngOnDestroy() {
    this.sub.unsubscribe();
  }
Run Code Online (Sandbox Code Playgroud)

服务

  properties: Property[];

  constructor( private propertyService: PropertyService) {}

  public getPropertyToDisplay(id: number): Observable<Property> {
    if (this.properties) {
      return this.findPropertyObservable(id);
    } else {
            return Observable.create((observer: Observer<Property>) => {
                this.getProperties().subscribe((properties: Property[]) => {
                    this.properties = properties;
                    const prop = this.filterProperties(id);
                    observer.next(prop);
                    observer.complete();
                })
            }).catch(this.handleError);
    }
  }

  private findPropertyObservable(id: number): Observable<Property> {
    return this.createObservable(this.filterProperties(id));
  }

  private filterProperties(id: number): Property {
        const props = this.properties.filter((prop) => prop.id == id);
        return (props.length) ? props[0] : null;
    }

  private createObservable(data: any): Observable<any> {
        return Observable.create((observer: Observer<any>) => {
            observer.next(data);
            observer.complete();
        });
    }

  private handleError(error: any) {
      console.error(error);
      return Observable.throw(error.json().error || 'Server error');
  }

  private getProperties(): Observable<Property[]> {
    if (!this.properties) {
    return this.propertyService.getProperties().map((res: Property[]) => {
      this.properties = res;
      console.log('The properties: ' + JSON.stringify(this.properties));
      return this.properties;
    })
      .catch(this.handleError);
    } else {
      return this.createObservable(this.properties);
      }
  }
Run Code Online (Sandbox Code Playgroud)