如何将数据从子路线传递到父路线(使用提交表单)

时间:2019-02-12 00:02:09

标签: angular

我有一个组件,其中包含带有 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))
        );
    }
}

1 个答案:

答案 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的状态管理库。