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

查看:24
本文介绍了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天全站免登陆