【问题标题】:How to refer a funtion as a template variable in Ionic Angular app?如何在 Ionic Angular 应用程序中将函数引用为模板变量?
【发布时间】:2020-04-09 12:49:47
【问题描述】:

我有一个Order 对象和一个客户对象。 Order 对象的 JSON payload 如下所示:

{
  "order_number" : 1,
  "customer_id": 1
}

这是JSON payloadCustomer 对象

{
  "customer_id": 1,
  "customer_name" : 1,
}

我有订单页面,我想在其中显示订单列表。但不是order.customer_id,而是显示customer_name

对于我有getCustomerById,它将customer_id 作为参数并返回customer_name

这是我的OrdersPage 班级:

import { Component, OnInit } from '@angular/core';
import { OrderService } from '../../services/order.service';
import { Order } from '../../models/order.model';
import { NavController, LoadingController } from '@ionic/angular';
import { Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { CustomerService } from 'src/app/services/customer.service';
import { Customer } from 'src/app/models/customer.model';

@Component({
  selector: 'app-orders',
  templateUrl: './orders.page.html',
  styleUrls: ['./orders.page.scss'],
})
export class OrdersPage implements OnInit {
  sender;
  customerName: string;
  destinationName: string;
  // viewOrders = false;
  error;
  orders: Order[];
  subscription: Subscription;
  constructor(private orderService: OrderService,
              private navCtrl: NavController,
              private router: Router,
              private customerService: CustomerService
            ) { }

  ngOnInit() {
    this.orderService.refreshNeeded
      .subscribe(() => {
        this.getAllOrders();
      });
    this.getAllOrders();

  }

  getAllOrders() {

    this.orderService.getAllOrders().subscribe(
      (res: Order[]) => {
        this.orders = res;

      },
      (error) => {
        this.error = error;

      });
  }

  getCustomerById(customerId: number): string {

    this.customerService.getCustomerById(customerId).subscribe(
      (customer: Customer) => {
        this.customerName = customer.name;
      }
    );
    return this.customerName;
  }

}

这是orders.page.html

<ion-header>
  <ion-toolbar color="dark">
    <ion-button slot="end">
      <ion-menu-button> </ion-menu-button>
    </ion-button>
    <ion-title>Orders</ion-title>
  </ion-toolbar>
</ion-header>

<ion-content>
  <ion-row>
    <ion-col size-md="8" offset-md="2">
      <ion-row class="header-row ion-text-center">
        <ion-col>
          Order number
        </ion-col>
        <ion-col>
          Customer
        </ion-col>
      </ion-row>
      <ion-row *ngFor="let order of orders; let i = index" class="data-row ion-text-center">
        <ion-col>
          {{order.order_number}}
        </ion-col>
        <ion-col>
          {{order.customer_id}}
        </ion-col>

        <!-- <ion-col>
        {{getCustomerById(order?.customer_id)}}
      </ion-col> -->
      </ion-row>
    </ion-col>
  </ion-row>
</ion-content>

此 html 有效,但它返回 order.customer_id 而不是 customer_name 我试图通过以这种方式调用模板中的函数来获取名称{{getCustomerById(order?.customer_id)}} 不起作用并且控制台中也没有错误。

在订单列表中获取customer_name 字段的最佳方式是什么?

这是我的customer.service.ts

import { Injectable } from '@angular/core';
import { HttpClient } from '@angular/common/http';
import { Observable, Subject } from 'rxjs';
import { Customer } from '../models/customer.model';
import { catchError, tap } from 'rxjs/operators';

@Injectable({
  providedIn: 'root'
})
export class CustomerService {
  url = 'http://api.mydomain.com';

  constructor( ) { }

  getAllCustomers(): Observable<Customer[]> {
    return this.httpClient.get<Customer[]>(`${this.url}/customers`).pipe();
  }

  getCustomerById(id: number): Observable<Customer> {
    return this.httpClient.get<Customer>(`${this.url}/customer/${id}`).pipe();
  }


}

【问题讨论】:

  • this.customerService.getCustomerById 这是异步的吗?
  • 有很多地方需要纠正。首先,这个订单对象应该有一个来自后端的 customer_name 字段,因为在每次订单迭代时调用服务器从来都不是一个好主意。
  • this.customerService.getCustomerById async 函数返回任何内容之前调用 getCustomerById 中的 return 语句,因为您没有使用 await。
  • @MuhammadUmair,现在我明白了,实际上它不是异步的。我现在已经在问题中包含了 CustomerService 代码。现在我想保持我的 API 不变。
  • 有没有办法在stackoverflow上聊天?

标签: angular typescript ionic4 angular-template-variable


【解决方案1】:

正如@Muhammad Umair 所提到的,为每个客户名称向服务器发出请求并不是一个好的设计。最好是发出一个请求来获取所有想要的客户名称。下面的解决方案没有考虑到这一点。

这里最好使用管道。

“管道将数据作为输入并将其转换为所需的输出。” 角度文档

请注意,您获取用户名的请求是异步的(这就是模板中没有显示任何内容的原因),在这里您还需要使用异步管道:

<ion-col> 
    {{ order.customer_id | getCustomerName | async }} 
</ion-col>

这是管道(您应该将其插入到组件模块的声明中。

import { Pipe } from '@angular/core';

@Pipe({
  name: 'getCustomerName'
})
export class CustomerNamePipe {

  constructor(private customerService: CustomerService) { }

  transform(userIds, args) {
     return this.customerService.getCustomerById(curstomerId);
  }

}

【讨论】:

  • 您认为每次迭代都与服务器联系是个好主意吗?
  • @Noelmout,此管道返回的是客户对象而不是字段,对吗?
【解决方案2】:

同样不是一个很好的解决方案,但考虑到您无法更改 API 中的任何内容的情况。您可以将您的文件修改为此。

import { Component, OnInit } from '@angular/core';
import { OrderService } from '../../services/order.service';
import { Order } from '../../models/order.model';
import { NavController, LoadingController } from '@ionic/angular';
import { Router } from '@angular/router';
import { Subscription } from 'rxjs';
import { CustomerService } from 'src/app/services/customer.service';
import { Customer } from 'src/app/models/customer.model';

@Component({
  selector: 'app-orders',
  templateUrl: './orders.page.html',
  styleUrls: ['./orders.page.scss'],
})
export class OrdersPage implements OnInit {
  sender;
  customerName: string;
  destinationName: string;
  // viewOrders = false;
  error;
  orders: Order[];
  subscription: Subscription;
  constructor(private orderService: OrderService,
              private navCtrl: NavController,
              private router: Router,
              private customerService: CustomerService
            ) { }

  ngOnInit() {
    this.orderService.refreshNeeded
      .subscribe(() => {
        this.getAllOrders();
        this.getAllCustomers();
      });

    this.getAllOrders();
    this.getAllCustomers();

  }

  getAllOrders() {

    this.orderService.getAllOrders().subscribe(
      (res: Order[]) => {
        this.orders = res;

      },
      (error) => {
        this.error = error;

      });
  }

  getAllCustomers() {

    this.customerService.getAllCustomers().subscribe(
      (customers: Customer[]) => {
        this.customers = customers;
      }
      (error) => {
        this.error = error;

      });
  }

  getCustomerById(customerId: number): string {
    const customer = this.customers.filter(customer => customer.customer_id === customerId );
    return customer.customer_name;
  }

}

【讨论】:

    【解决方案3】:

    正如@Noelmout 提到的使用管道,我只需稍作改动即可获得customer_name

    这是CustomerNamePipe

    import { Pipe, PipeTransform } from '@angular/core';
    import { CustomerService } from '../services/customer.service';
    import { Customer } from '../models/customer.model';
    import { pluck } from 'rxjs/operators';
    
    @Pipe({
      name: 'getCustomerName'
    })
    export class CustomerNamePipe implements PipeTransform {
    
      customer: Customer;
    
      constructor(private customerService: CustomerService) { }
    
      transform(curstomerId, args) {
        return this.customerService.getCustomerById(curstomerId).pipe(pluck('customer_name'));
    
      }
    
    
    }
    

    这是 order.page.html

    <ion-col> 
        {{ order.customer_id | getCustomerName | async }} 
    </ion-col>
    

    【讨论】:

      猜你喜欢
      • 2021-01-25
      • 2019-01-06
      • 2019-03-12
      • 2018-07-14
      • 2017-04-27
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-12-08
      相关资源
      最近更新 更多