填写这份《一分钟调查》,帮我们(开发组)做得更好!去填写Home

表单

Forms

管理数据结束时,这个在线商店应用有了一个商品名录和一个购物车。

At the end of Managing Data, the online store application has a product catalog and a shopping cart.

在本节中,你将通过添加基于表单的结帐功能来完成该应用。你还将创建一个表单来收集用户信息,作为结账过程的一部分。

In this section, you'll finish the app by adding a form-based checkout feature. You'll create a form to collect user information as part of checkout.

Angular 中的表单

Forms in Angular

Angular 中的表单采用了基于 HTML 表单的标准功能,并添加了一个编排层,以帮助你创建自定义表单控件,并提供了出色的验证体验。Angular 响应式表单有两个部分,组件中那些用于存储和管理表单的对象,以及表单在模板中的可视化。

Forms in Angular take the standard capabilities of the HTML based forms and add an orchestration layer to help with creating custom form controls, and to supply great validation experiences. There are two parts to an Angular Reactive form, the objects that live in the component to store and manage the form, and the visualization of the form that lives in the template.

定义结帐的表单模型

Define the checkout form model

首先,你要设置一个结账的表单模型。表单模型是表单状态的真相之源(source of truth),它是在组件类中定义的。

First, you'll set up the checkout form model. The form model is the source of truth for the status of the form and is defined in the component class.

  1. 打开 cart.component.ts

    Open cart.component.ts.

  2. Angular 的 FormBuilder 服务为生成控件提供了方便的方法。和你使用过的其它服务一样,你需要导入并注入该服务,然后才能使用它:

    Angular's FormBuilder service provides convenient methods for generating controls. As with the other services you've used, you need to import and inject the service before you can use it:

    1. @angular/forms 包中导入 FormBuilder 服务。

      Import the FormBuilder service from the @angular/forms package.

      import { Component } from '@angular/core'; import { FormBuilder } from '@angular/forms'; import { CartService } from '../cart.service';
      src/app/cart/cart.component.ts
            
            import { Component } from '@angular/core';
      import { FormBuilder } from '@angular/forms';
      
      import { CartService } from '../cart.service';
          

      FormBuilder 服务是由 ReactiveFormsModule 提供的,它已经在之前修改过的 AppModule 定义过(在 app.module.ts )。

      The FormBuilder service is provided by the ReactiveFormsModule, which is already defined in the AppModule you modified previously (in app.module.ts).

    2. 注入这个 FormBuilder 服务。

      Inject the FormBuilder service.

      export class CartComponent { items; constructor( private cartService: CartService, private formBuilder: FormBuilder, ) { } }
      src/app/cart/cart.component.ts
            
            export class CartComponent {
        items;
      
        constructor(
          private cartService: CartService,
          private formBuilder: FormBuilder,
        ) {
        }
      }
          
  3. CartComponent 类中,定义 checkoutForm 属性来存储表单模型。

    In the CartComponent class, define the checkoutForm property to store the form model.

    export class CartComponent { items; checkoutForm; }
    src/app/cart/cart.component.ts
          
          export class CartComponent {
      items;
      checkoutForm;
    }
        
  4. 在结帐时,该应用会提示用户输入姓名和地址。这样你接下来就可以收集到这些信息了。可以使用 FormBuilder#group() 方法,用一个包含 nameaddress 字段的表单模型赋值给 checkoutForm 属性。

    During checkout, the app will prompt the user for a name and address. So that you can gather that information later, set the checkoutForm property with a form model containing name and address fields, using the FormBuilder#group() method.

    export class CartComponent { items; checkoutForm; constructor( private cartService: CartService, private formBuilder: FormBuilder, ) { this.items = this.cartService.getItems(); this.checkoutForm = this.formBuilder.group({ name: '', address: '' }); } }
    src/app/cart/cart.component.ts
          
          export class CartComponent {
      items;
      checkoutForm;
    
      constructor(
        private cartService: CartService,
        private formBuilder: FormBuilder,
      ) {
        this.items = this.cartService.getItems();
    
        this.checkoutForm = this.formBuilder.group({
          name: '',
          address: ''
        });
      }
    }
        
  5. 对于结帐过程,用户需要能够提交表单数据(他们的姓名和地址)。在提交订单之后,表单应该重置,购物车应该清空。

    For the checkout process, users need to be able to submit the form data (their name and address). When the order is submitted, the form should reset and the cart should clear.

    cart.component.ts 中,定义一个 onSubmit() 方法来处理表单。使用 CartService#clearCart() 方法清空购物车项目,并在提交完之后重置该表单。(在实际应用中,此方法也会把数据提交给外部服务器。)

    In cart.component.ts, define an onSubmit() method to process the form. Use the CartService#clearCart() method to empty the cart items and reset the form after it is submitted. (In a real-world app, this method also would submit the data to an external server.)

    整个购物车组件如下所示:

    The entire cart component is shown below:

    import { Component } from '@angular/core'; import { FormBuilder } from '@angular/forms'; import { CartService } from '../cart.service'; @Component({ selector: 'app-cart', templateUrl: './cart.component.html', styleUrls: ['./cart.component.css'] }) export class CartComponent { items; checkoutForm; constructor( private cartService: CartService, private formBuilder: FormBuilder, ) { this.items = this.cartService.getItems(); this.checkoutForm = this.formBuilder.group({ name: '', address: '' }); } onSubmit(customerData) { // Process checkout data here console.warn('Your order has been submitted', customerData); this.items = this.cartService.clearCart(); this.checkoutForm.reset(); } }
    src/app/cart/cart.component.ts
          
          
    1. import { Component } from '@angular/core';
    2. import { FormBuilder } from '@angular/forms';
    3.  
    4. import { CartService } from '../cart.service';
    5.  
    6. @Component({
    7. selector: 'app-cart',
    8. templateUrl: './cart.component.html',
    9. styleUrls: ['./cart.component.css']
    10. })
    11. export class CartComponent {
    12. items;
    13. checkoutForm;
    14.  
    15. constructor(
    16. private cartService: CartService,
    17. private formBuilder: FormBuilder,
    18. ) {
    19. this.items = this.cartService.getItems();
    20.  
    21. this.checkoutForm = this.formBuilder.group({
    22. name: '',
    23. address: ''
    24. });
    25. }
    26.  
    27. onSubmit(customerData) {
    28. // Process checkout data here
    29. console.warn('Your order has been submitted', customerData);
    30.  
    31. this.items = this.cartService.clearCart();
    32. this.checkoutForm.reset();
    33. }
    34. }

表单模型是在组件类中定义的。要在视图中反映这个模型,你需要创建一个结帐表单。

The form model is defined in the component class. To reflect the model in the view, you'll need a checkout form.

创建结帐表单

Create the checkout form

接下来,你将在“购物车”页面的底部添加一个结帐表单。

Next, you'll add a checkout form at the bottom of the "Cart" page.

  1. 打开 cart.component.html

    Open cart.component.html.

  2. 在模板的底部,添加一个空的 HTML 表单来捕获用户信息。

    At the bottom of the template, add an empty HTML form to capture user information.

  3. 使用 formGroup 属性绑定把 checkoutForm 绑定到模板中的 form 标签上。还要提供一个 “Purchase” 按钮来提交表单。

    Use a formGroup property binding to bind the checkoutForm to the form tag in the template. Also include a "Purchase" button to submit the form.

    <form [formGroup]="checkoutForm"> <button class="button" type="submit">Purchase</button> </form>
    src/app/cart/cart.component.html
          
          <form [formGroup]="checkoutForm">
    
      <button class="button" type="submit">Purchase</button>
    
    </form>
        
  4. form 标签上,使用 ngSubmit 事件绑定来监听表单提交,并使用 checkoutForm 值调用 onSubmit() 方法。

    On the form tag, use an ngSubmit event binding to listen for the form submission and call the onSubmit() method with the checkoutForm value.

    <form [formGroup]="checkoutForm" (ngSubmit)="onSubmit(checkoutForm.value)"> </form>
          
          <form [formGroup]="checkoutForm" (ngSubmit)="onSubmit(checkoutForm.value)">
    </form>
        
  5. nameaddress 添加输入字段。使用 formControlName 属性绑定来把 checkoutForm 表单控件中的 nameaddress 绑定到它们的输入字段。最终的完整版组件如下所示:

    Add input fields for name and address. Use the formControlName attribute binding to bind the checkoutForm form controls for name and address to their input fields. The final complete component is shown below:

    <h3>Cart</h3> <p> <a routerLink="/shipping">Shipping Prices</a> </p> <div class="cart-item" *ngFor="let item of items"> <span>{{ item.name }} </span> <span>{{ item.price | currency }}</span> </div> <form [formGroup]="checkoutForm" (ngSubmit)="onSubmit(checkoutForm.value)"> <div> <label>Name</label> <input type="text" formControlName="name"> </div> <div> <label>Address</label> <input type="text" formControlName="address"> </div> <button class="button" type="submit">Purchase</button> </form>
          
          
    1. <h3>Cart</h3>
    2.  
    3. <p>
    4. <a routerLink="/shipping">Shipping Prices</a>
    5. </p>
    6.  
    7. <div class="cart-item" *ngFor="let item of items">
    8. <span>{{ item.name }} </span>
    9. <span>{{ item.price | currency }}</span>
    10. </div>
    11.  
    12. <form [formGroup]="checkoutForm" (ngSubmit)="onSubmit(checkoutForm.value)">
    13.  
    14. <div>
    15. <label>Name</label>
    16. <input type="text" formControlName="name">
    17. </div>
    18.  
    19. <div>
    20. <label>Address</label>
    21. <input type="text" formControlName="address">
    22. </div>
    23.  
    24. <button class="button" type="submit">Purchase</button>
    25. </form>

往购物车中放入几件商品之后,用户可以查看这些商品,输入自己的姓名和地址,进行购买:

After putting a few items in the cart, users can now review their items, enter name and address, and submit their purchase:

Cart page with checkout form

下一步

Next steps

恭喜!你有了一个完整的在线商店应用,它具有商品名录,购物车和结账功能。

Congratulations! You have a complete online store application with a product catalog, a shopping cart, and a checkout function.

继续浏览“部署”部分,把你的应用转移到本地开发、部署到 Firebase 或你自己的服务器。

Continue to the "Deployment" section to move to local development, or deploy your app to Firebase or your own server.