目标:我正在尝试创建一个具有可订阅数组(BehaviorSubject)的服务,这样当我更新服务中的数据时,更改会反映在正在使用的客户端组件中它。我决定在添加或更改项目时首先尝试在服务器中保留持久性列表,然后我会担心保持数据与服务器一致。
问题:
workCategories:Rx.BehaviorSubject>在服务中似乎没有保留它分配的数据。从第一个客户端组件调用它,然后当第二个客户端组件使用该服务时,workCategories再次为null。
服务
import { Component, Injectable } from "@angular/core";
import { Http, Response, Headers, RequestOptions, RequestMethod, Request } from "@angular/http";
import { WorkCategory } from "./models";
import { Observable } from "rxjs/Observable";
import * as Rx from "rxjs/Rx";
@Injectable()
export class WorkCategoryService {
public workCategories: Rx.BehaviorSubject<Array<WorkCategory>>;
private _workCategories: Array<WorkCategory> = [];
constructor(public http: Http) {
console.log("!!!!WorkCat Service Constructor Called!!!");
this.getWorkCategories();
}
addWorkCategory(wc: WorkCategory): number {
//** when this is called after component is instantiated and getWorkCategories() is called this.workCategories is null
console.log("Add Work Category Called in Service for \"" + wc.name + "\"");
let newID: number;
let headers = new Headers();
headers.append('Content-Type', 'application/json');
let options = new RequestOptions({ headers: headers });
let blah = this.http.post('./api/workcategories', JSON.stringify(wc), options).subscribe((res: Response) => newID = res.json());
if (this._workCategories != null) {
console.log("Added to private");
this._workCategories.push(wc);
}
//** fails here and the page is reloaded due to this.workCategories being null
this.workCategories.next(this._workCategories);
return newID;
}
getWorkCategories(): Observable<Array<WorkCategory>> {
console.log("Get Work Category Called in Service");
var blah = this.http.get('./api/workcategories')
.map(this.WorkCategoriesResponseMapper)
console.log("Get Work Category Done in Service");
return blah;
}
WorkCategoriesResponseMapper(response: Response) {
var temp = response.json();
if (this.workCategories == null) {
this._workCategories = temp;
this.workCategories = new Rx.BehaviorSubject(this._workCategories);
}
else {
this._workCategories = temp;
this.workCategories.next(this._workCategories);
}
return temp;
}
}
第一个客户端组件
这会调用this.workCatServ.getWorkCategories()并订阅它。
import { Component, Input, Injectable, ViewChild, EventEmitter, Output, } from "@angular/core";
import { Http, Response, Headers, RequestOptions, RequestMethod, Request } from "@angular/http";
import { WorkCategory } from "./models";
import { WorkCategoryService } from "./workcategories.service";
//import { Observable } from 'rxjs/Observable';
import * as Rx from "rxjs/Rx";
import { TreeNode, MenuItem, Message } from 'primeng/primeng';
import { CategoryAdderUpdateComponent } from "./category-adder-update.component";
@Component({
selector: 'workcategories_view',
//providers: [WorkCategoryService],
templateUrl: './app/workcategories-view.html'
})
@Injectable()
export class WorkCategoriesViewComponent {
@ViewChild(CategoryAdderUpdateComponent) private CategoryCU: CategoryAdderUpdateComponent;
@Output() GrowlMsg = new EventEmitter<Message>();
workCats: Array<WorkCategory>;
tree: TreeNode[];
selectedNode: TreeNode;
selectedCategory: WorkCategory = new WorkCategory(-1,"Blank",-2);
contextMenuItems: MenuItem[];
CUWorkCatVisible: boolean = false;
CUWorkCatEdit: boolean = false;
CUViewHeader: string;
constructor(public http: Http, private workCatServ: WorkCategoryService) {
}
ngOnInit() {
console.log("Work Categories view called");
this.workCatServ.getWorkCategories().subscribe(result => this.convertToTreeNodes(result), error => console.error(error), () => { });
this.contextMenuItems = [
{
label: 'Add',
icon: 'fa-plus',
command: (event) => { this.displayAddWorkCat() }
},
{
label: 'Edit',
icon: 'fa-edit',
command: (event) => { this.displayEditWorkCat() }
},
{
label: 'Delete',
icon: 'fa-eraser',
command: (event) => { this.displayDeleteWorkCat() }
}
];
}
displayAddWorkCat() {
this.selectedCategory = this.workCats.find(b => b.id == this.selectedNode.data);
//console.log("Add " + this.selectedCategory.name);
this.CategoryCU.AddView(this.selectedCategory);
this.CUViewHeader = "Add Work Category";
/*this.workCatServ.findWorkCategorey(this.selectedNode.data).map(result => {
console.log("Done");
this.selectedCategory = result;
});
*/
this.CUWorkCatVisible = true;
}
displayEditWorkCat() {
this.selectedCategory = this.workCats.find(x => x.id == this.selectedNode.data);
//console.log("Edit " + this.selectedCategory.name);
this.CategoryCU.UpdateView(this.selectedCategory);
this.CUViewHeader = "Edit \"" + this.selectedCategory.name + "\" Work Category";
/*this.workCatServ.findWorkCategory(this.selectedNode.data).map(result => {
console.log("Done");
this.selectedCategory = result;
});*/
this.CUWorkCatVisible = true;
}
displayDeleteWorkCat() {
console.log("Delete");
}
passUpGrowlMsg(msg: Message) {
this.GrowlMsg.emit(msg);
}
MyTreeWalker(nodeId: number = 0, parentNode: TreeNode = null): boolean {
let blah = this.workCats.filter(x => x.parentId == nodeId);
if (blah.length == 0) {
//console.log("Node " + nodeId + " is leaf");
return false;
}
//console.log("Node " + nodeId + " is branch, " + blah.length + " children");
if (nodeId != 0) {
for (var b of blah) {
var TempNode: TreeNode = { label: b.name, data: b.id, parent: parentNode, children: [] };
this.MyTreeWalker(b.id, TempNode);
//console.log("Control Passed Back");
parentNode.children.push(TempNode);
//console.log("Pass End");
}
} else {
for (var c of blah) {
var TempNode: TreeNode = { label: c.name, data: c.id, parent: parentNode, children: [] };
this.MyTreeWalker(c.id, TempNode);
//console.log("R - Control Passed Back");
this.tree.push(TempNode);
//console.log("R - Pass End");
}
}
//console.log("Node: " + nodeId + " Exit");
return true;
}
convertToTreeNodes(cats: WorkCategory[]) {
console.log("Tree Updated Called");
this.tree = new Array<TreeNode>();
this.workCats = cats;
this.MyTreeWalker();
}
}
第二个客户端组件
这会在服务中调用addWorkCategory()
import { Component, EventEmitter, Output, Input } from "@angular/core";
import { Http, Response } from "@angular/http";
import { WorkCategory} from "./models";
import { WorkCategoryService } from "./workcategories.service";
import { Message } from 'primeng/primeng';
import 'rxjs/add/operator/map';
@Component({
selector: 'category-adder-update',
//providers: [WorkCategoryService],
templateUrl: './app/category-adder-update.html'
})
export class CategoryAdderUpdateComponent {
@Output() GrowlMsg = new EventEmitter<Message>();
edit: boolean;
workcategories: Array<WorkCategory> = [];
tempCategory: WorkCategory;
parentCategory: WorkCategory;
buttonText: string = "Blanky Blank";
constructor(public http: Http, public workCategoriesServ: WorkCategoryService) {
this.tempCategory = new WorkCategory(null,"",null);
console.log("Category Adder-Update Called");
}
AddView(parentCat: WorkCategory) {
this.edit = false;
this.parentCategory = parentCat
this.tempCategory = new WorkCategory(null, "", parentCat.id);
this.buttonText = "Add Work Category";
}
UpdateView(cat: WorkCategory) {
this.edit = true;
this.parentCategory = null;
this.tempCategory = cat;
this.buttonText = "Update Work Category";
}
blahSubmit() {
if (this.edit) {
this.updateWorkCategory();
} else {
this.addWorkCategory();
}
}
getWorkCategories() {
console.log("jobs get called");
this.workCategoriesServ.getWorkCategories().subscribe(
result => this.workcategories = result,
error => console.error,
() => console.log('workcategories loaded: ' + this.workcategories.length));
}
addWorkCategory(): void {
this.GrowlMsg.emit({ severity: 'info', summary: 'Category Added', detail: "Category " + this.tempCategory.name + " added to " + this.parentCategory.name });
if (this.workCategoriesServ.addWorkCategory(this.tempCategory) != null) {
console.log("New Work Category Submitted");
}
else {
console.error("New Work Category NOT Submitted");
}
}
}
应用模块
@NgModule({
imports: [BrowserModule, HttpModule, FormsModule, DataTableModule, CalendarModule, TreeModule, TabViewModule, GrowlModule, DialogModule, ContextMenuModule, RouterModule.forRoot(appRoutes) ],
declarations: [AppComponent, TicketAdderComponent, JobsViewComponent, TimeEntriesViewComponent, WorkCategoriesViewComponent, CategoryAdderUpdateComponent],
providers: [WorkCategoryService],
entryComponents: [TicketAdderComponent],
bootstrap: [AppComponent ]
})
export class AppModule { }
答案 0 :(得分:2)
您在每个组件中提供服务。您要做的是在AppModule中提供服务,然后两个组件将共享相同的服务。