Angular 4-将对象从一个组件传递到另一个组件(无父级-子级层次结构) [英] Angular 4 - Pass an object from one component to another (no parent - child hierarchy)

查看:69
本文介绍了Angular 4-将对象从一个组件传递到另一个组件(无父级-子级层次结构)的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我的情况:

我有一个显示图块的组件,每个图块代表一个用ngfor遍历的数组中的对象. 单击磁贴时,我要将对象传递给其他组件,该组件负责在可修改的字段中显示该对象的所有属性.

I have a component showing tiles with each tile representing an object from an array that is looped over with an ngfor. When a tile is clicked I want to pass the object to a different component, which is responsable for displaying all properties of that object in fields that can be modified.

我尝试过的事情:

在进行了一些研究之后,我遇到了许多帖子,向我展示了如何为父子层次结构实现这一目标,还有一些帖子解释了必须使用共享服务才能实现所需的功能,我决定尝试设置这样的服务.

After doing some research and coming across multiple posts showing me how to achieve this for a parent - child hierarchy and some posts explaining that it is necessary to use a shared service in order to achieve the wanted funcitonality, I decided to try and setup such a service.

但是,我似乎没有得到什么,是当我应该导航到其他路线时.似乎导航是在早期发现的,因为在详细信息组件中检索传递给服务的对象时,它是未定义的.

However, what I don't seem to get is when I should navigate to the different route. It seems that the navigation finds place to early as the object passed to the service is undefined when retrieving it in the detail component.

我的代码:

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

The component showing the tiles has the following function to pass the clicked object to the shared service:

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

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

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

The shared service has a function to set a property object and one to retrieve it and looks like this:

@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();
  }
}

最后,详细信息组件必须接收单击的对象但得到未定义的对象:

Finally the detail component which has to receive the object that was clicked on but gets an undefined object:

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();
  }
}

提前谢谢!

推荐答案

我通过传递被点击的图块对象的ID(如该路线的导航额外信息一样)来解决了该问题,然后详细使用了一项服务组件,以根据通过路由的ID来获取对象.

I solved the problem by passing the id of the object of the tile that was clicked as in the navigation extras of the route and then use a service in the detail component to fetch the object based on the id passed through the route.

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

I will provide the code below so hopefully nobody has to go through all of this ever again.

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

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

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

    this.router.navigate(['/properties/detail'], navigationExtras);
  }

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

  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();
  }

服务

  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);
      }
  }

这篇关于Angular 4-将对象从一个组件传递到另一个组件(无父级-子级层次结构)的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆