我的情况:
我有一个显示图块的组件,每个图块表示一个数组的对象,该数组使用ngfor循环。 单击一个图块时,我想将该对象传递给另一个组件,该组件负责在可以修改的字段中显示该对象的所有属性。
我尝试了什么:
经过一些研究并发现多篇帖子向我展示如何为父母 - 子级层次结构实现这一点,以及一些帖子解释为了实现所需的功能需要使用共享服务,我决定尝试设置这样的服务。
但是,我似乎无法获得的是当我应该导航到不同的路线时。似乎导航在早期找到了位置,因为在详细信息组件中检索它时,传递给服务的对象是未定义的。
我的代码:
显示切片的组件具有以下功能,可将单击的对象传递给共享服务:
editPropertyDetails(property: Property) {
console.log('Edit property called');
return new Promise(resolve => {
this.sharedPropertyService.setPropertyToDisplay(property);
resolve();
}).then(
() => this.router.navigate(['/properties/detail'])
)
}
共享服务具有设置属性对象的功能和检索它的功能,如下所示:
@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();
}
}
最后,详细信息组件必须接收单击的对象,但获取未定义的对象:
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();
}
}
提前致谢!
答案 0 :(得分:5)
我通过传递在路径的导航附加内容中单击的tile的对象的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);
}
接收点击的对象的详细信息组件
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);
}
}
答案 1 :(得分:4)
请尝试以下示例:
第1步:创建服务[DataService]
import { Injectable } from '@angular/core';
import { BehaviorSubject } from 'rxjs/BehaviorSubject';
@Injectable()
export class DataService {
private userIdSource = new BehaviorSubject<number>(0);
currentUser = this.userIdSource.asObservable();
private orderNumSource = new BehaviorSubject<number>(0);
currentOrder = this.orderNumSource.asObservable();
constructor() { }
setUser(userid: number) {
this.userIdSource.next(userid)
}
setOrderNumber(userid: number) {
this.orderNumSource.next(userid)
}
}
步骤2:在登录组件中设置值
import { Component } from '@angular/core';
import { DataService } from "../services/data.service";
@Component({
selector: 'app-login',
templateUrl: './login.component.html',
styleUrls: ['./login.component.css']
})
export class LoginComponent {
constructor( private dataService:DataService) { }
onSubmit() {
this.dataService.setUser(1);
}
}
第3步:在另一个组件中获取价值
import { Component, OnInit } from '@angular/core';
import { DataService } from "../services/data.service";
@Component({
selector: 'app-shopping-cart',
templateUrl: './shopping-cart.component.html',
styleUrls: ['./shopping-cart.component.css']
})
export class ShoppingCartComponent implements OnInit {
userId: number = 0;
constructor(private dataService: DataService) { }
ngOnInit() {
this.getUser();
}
getUser() {
this.dataService.currentUser.subscribe(user => {
this.userId = user
}, err => {
console.log(err);
});
}
}
注意:在页面刷新时,该值将丢失。
答案 2 :(得分:3)
使用服务 首先,您要在服务上创建一个功能。 调用该功能,并根据其他组件使用。 编写这段代码
this.handleReq.handlefilterdata.subscribe(() => {
this.ngDoCheck();
});
在这里, handleReq是服务。 handlefilterdata是rxjs的主题。
答案 3 :(得分:0)
尝试这样:
尝试订阅this.sharedPropertyService.propertyToDisplay
而不是this.sharedPropertyService.getPropertyToDisplay()
this.sharedPropertyService.propertyToDisplay.subscribe((property) => {
this.property = property;
console.log('Detail Component: ' + property.description);
});
并发送如下对象:
editPropertyDetails(property: Property) {
this.sharedPropertyService.setPropertyToDisplay(property);
}
答案 4 :(得分:0)
你的控制台输出了什么?是否已在子组件上设置this.property?
我会尝试摆脱这个功能
getPropertyToDisplay():Observable
并尝试直接访问propertyToDisplay。
同样.navigate可以将数据作为第二个参数,因此您可以尝试在路径更改中传递数据。
constructor(
private route: ActivatedRoute,
private router: Router) {}
ngOnInit() {
this.property = this.route
.variableYouPassedIntoNavigator
答案 5 :(得分:0)
我正在研究类似的功能,并且遇到了相同的问题(未定义)。您可以这样初始化。
public propertyToDisplay = new BehaviorSubject<Property>(undefined);
进行这样的更改后。我可以从Observable
的值中获取服务文件以及尝试使用此服务的组件中的值。