我有一个组件,其中包含带有 New Expense 按钮的费用列表。点击后,它将转到其子路线,如下所示:
<a [routerLink]="['./new']">New Expense</a>
此新费用组件是一种接受用户输入并创建新费用的表格。然后,它使用服务将其添加到数据库中。
问题是ExpensesComponent
(带有列表的那个)不会更新,因为它仅检查数据库以最初通过ngOnInit()
来填充费用列表。
ngOnInit() {
this.expenseService.getExpenses()
.subscribe(expenses => this.expenses = expenses);
}
我在网上看到的示例的输入与表单具有相同的组件,因此在使用http发布请求将其添加到数据库后,他们可以简单地将其“推送”到列表中,从而可以直观地更新“地方”。
我的目标是复制这种效果。我想将其添加到列表中,以便用户可以看到它,而不仅仅是将其发布到数据库中。有没有一种方法可以将此费用从子级路由发送到父级,还是应该添加到数据库中并让ExpensesComponent
重新加载列表,而不是仅在ngOnInit()
期间发生?以下是我认为是相关的代码。我从中删除了一些东西以消除混乱,因此它实际上不会运行。我只是在寻找最好的方法,而不是真正的代码。
例如,我知道是否在模板中我没有使用路由,而是像这样<app-new-expenses></app-new-expenses>
那样调用了子组件。有一种使用发射器的方法,所以我使用路径显示此组件是错的吗?
费用组件,其中包含该列表:
@Component({
selector: 'app-expenses',
templateUrl: './expenses.component.html',
styleUrls: ['./expenses.component.css']
})
export class ExpensesComponent implements OnInit {
expenses: Expense[];
constructor(private expenseService: ExpenseService) {
}
ngOnInit() {
this.expenseService.getExpenses()
.subscribe(expenses => this.expenses = expenses);
}
getExpense(id: number) {
//console.log(this.expenseService.getExpense(id));
}
}
新费用组件,其中包含以下格式:
@Component({
selector: 'app-new-expense',
templateUrl: './new-expense.component.html',
styleUrls: ['./new-expense.component.css']
})
export class NewExpenseComponent implements OnInit {
model: Expense;
types: string[];
constructor(
private router: Router,
private expenseService: ExpenseService) { }
ngOnInit() {
this.model = new Expense(0, 40, "Virgin Mobile", "2019/10/12", "Fixed");
this.types = ['Fixed', 'Periodic', 'Variable'];
}
onSubmit(amount, place, date) {
var expense = new Expense(6, amount, place, date, "Fixed");
this.expenseService.addExpense(expense).subscribe(
);
}
}
费用服务:
@Injectable({
providedIn: 'root'
})
export class ExpenseService {
expenses$: Observable<Expense[]>;
constructor(private http: HttpClient) { }
getExpenses(): Observable<Expense[]> {
this.expenses$ = this.http.get<Expense[]>('http://localhost:8000/expenses');
return this.expenses$;
}
addExpense(expense: Expense): Observable<Expense> {
return this.http.post<Expense>("http://localhost:8000/expenses", expense);
}
getExpense(id: number | string) {
return this.getExpenses().pipe(
map((expenses: Expense[]) => expenses.find(expense => expense.id === +id))
);
}
}
答案 0 :(得分:0)
是的,您可以修改服务以保留费用列表。
以下是我的一项服务的示例。这还会通知组件“所选产品”应更改为列表中新添加的产品。
@Injectable({
providedIn: 'root'
})
export class ProductService {
private productsUrl = 'api/products';
private products: IProduct[];
private selectedProductSource = new BehaviorSubject<IProduct | null>(null);
selectedProductChanges$ = this.selectedProductSource.asObservable();
constructor(private http: HttpClient) { }
getProducts(): Observable<IProduct[]> {
if (this.products) {
return of(this.products);
}
return this.http.get<IProduct[]>(this.productsUrl)
.pipe(
tap(data => console.log(JSON.stringify(data))),
tap(data => this.products = data),
catchError(this.handleError)
);
}
createProduct(product: IProduct, headers: HttpHeaders): Observable<IProduct> {
return this.http.post<IProduct>(this.productsUrl, product, { headers: headers} )
.pipe(
tap(data => console.log('createProduct: ' + JSON.stringify(data))),
tap(data => {
this.products.push(data);
}),
catchError(this.handleError)
);
}
}
请注意,然后createProduct
方法会将数据推送到列表中。
您可以在此处找到完整的代码:https://github.com/DeborahK/Angular-Communication/tree/master/APM-Final
或者,您可以研究NgRx,它是Angular的状态管理库。