目標:我想創建一個具有可訂閱數組(BehaviorSubject)的服務,這樣當我更新服務中的數據時,這些更改將反映在客戶端正在使用它的組件。我決定首先嚐試在附加或更改項目時保留服務器中的持久性列表,然後再擔心保持數據與服務器的一致性。每個組件不共享一個服務的實例
問題:
workCategories:Rx.BehaviorSubject>在服務似乎沒有保持它就是它的分配數據。從第一個客戶端組件調用它時,然後當第二個客戶端組件使用該服務時,workCategories再次爲空。
服務
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;
}
}
1客戶端組件
這就要求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");
}
}
}
APP模塊
@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 { }
它不是非常持久,因爲它接縫。 –
@RomanC Whjat是否意味着? – TheColonel26
在計算機科學中,持久性指的是超越創造它的過程的狀態特徵。這在實踐中通過將狀態作爲數據存儲在計算機數據存儲器中來實現。程序必須向存儲設備傳輸數據和從存儲設備傳輸數據,並且必須提供從本地編程語言數據結構到存儲設備數據結構的映射。 –