• [Angular] Component architecture and Reactive Forms


    It it recommeded that when deals with form component, we can create a container component to hold state, and then create a stateless component to enpower the form.

    For example:

    In the example has two components, one is container component 'meal.component.ts', another is statless component 'meal-form.component.ts'.

    For the container component, it talks to service:

    import {Component} from '@angular/core';
    import {Meal} from '../../../shared/services/meals/meals.service';
    @Component({
      selector: 'meal',
      styleUrls: ['meal.component.scss'],
      template: `
        <div class="meal">
          <div class="meal__title">
            <h1>
              <img src="/img/food.svg" alt="Food">
              <span>Create meal</span>
            </h1>
          </div>
          <div>
            <meal-form
              (create)="addMeal($event)"
            ></meal-form>
          </div>
        </div>
      `
    })
    export class MealComponent {
      constructor() {
    
      }
    
      addMeal(meal: Meal) {
        console.log("meal", JSON.stringify(meal, null, 2))
      }
    }

    So 'addMeal' function will dispatch action to talk to the service.

    For statless component:

    import {ChangeDetectionStrategy, Component, EventEmitter, Output} from '@angular/core';
    import {FormBuilder, FormArray, FormGroup, FormControl, Validators} from '@angular/forms';
    import {Meal} from '../../../shared/services/meals/meals.service';
    @Component({
      selector: 'meal-form',
      changeDetection: ChangeDetectionStrategy.OnPush,
      styleUrls: ['meal-form.component.scss'],
      template: `
        <div class="meal-form"> 
          <form [formGroup]="form">
            <div class="meal-form__name">
              <label>
                <h3>Meal name</h3>
                <input type="text" 
                       formControlName="name"
                       placeholder="e.g. English Breakfast">
                <div class="error" *ngIf="required">
                  Workout name is required
                </div>
              </label>
            </div>
            
            <div class="meal-form__food">
              <div class="meal-form__subtitle">
                <h3>Food</h3>
                <button 
                  type="button" 
                  (click)="addIngredient()"
                  class="meal-form__add">
                  <img src="/img/add-white.svg" alt="Add food">
                  Add food
                </button>
              </div>
              <div formArrayName="ingredients">
                <label *ngFor="let c of ingredients.controls; index as i;">
                  <input type="text" [formControlName]="i" placeholder="e.g Eggs">
                  <span
                    class="meal-form__remove"
                    (click)="removeIngredient(i)"
                  ></span>
                </label>
              </div>
            </div>
            
            <div class="meal-form__submit">
              <div>
                <button type="button" class="button" (click)="createMeal()">
                  Create Meal
                </button>
                <a 
                  [routerLink]="['../']"
                  class="button button--cancel">
                  Cancel
                </a>
              </div>
            </div>
          </form>
        </div>
      `
    })
    export class MealFormComponent {
    
      @Output()
      create = new EventEmitter<Meal>();
    
      form = this.fb.group({
        name: ['', Validators.required],
        ingredients: this.fb.array([''])
      });
    
      get ingredients () {
        // Type check for ingredients, mark as FormArray
        // Therefore when we use 'ingredients',
        // We can get auto complete
        return this.form.get('ingredients') as FormArray;
      }
    
      get required() {
        return (
          this.form.get('name').hasError('required') &&
            this.form.get('name').touched
        );
      }
    
      constructor(private fb: FormBuilder) {
    
      }
    
      createMeal() {
        if (this.form.valid) {
          this.create.emit(this.form.value);
        }
      }
    
      addIngredient() {
        // Add a new FormControl to FormArray
        this.ingredients.push(new FormControl(''));
      }
    
      removeIngredient(i: number) {
        this.ingredients.removeAt(i);
      }
    }

    It uses ReactiveForm to create form.

    Things to be notice:

    1. Add type check for form array:

      get ingredients () {
        // Type check for ingredients, mark as FormArray
        // Therefore when we use 'ingredients',
        // We can get auto complete
        return this.form.get('ingredients') as FormArray;
      }

    Then whenever you use 'this.ingredients', it will show auto complete.

    2. FormArray method:

      addIngredient() {
        // Add a new FormControl to FormArray
        this.ingredients.push(new FormControl(''));
      }
    
      removeIngredient(i: number) {
        this.ingredients.removeAt(i);
      }
  • 相关阅读:
    北斗授时系统,GPS授时服务器—在行业应用及介绍
    GPS时间同步服务器,NTP时间同步服务器,——数据采集系统应用
    北斗卫星时钟(北斗授时服务器)厂家介绍及价格分析
    linux系统下ntp网络时钟服务器(NTP服务器)的搭建和使用
    2020年SAP项目艰辛曲折的开工历程 III
    2020年SAP项目艰辛曲折的开工历程 II
    2020年SAP项目艰辛曲折的开工历程 I
    2020年肺炎疫情期间看的几部古装电视剧
    做人不忘本,才能走得更远 --- 我看电视剧《雍正王朝》
    邬先生及时功成身退,是明哲保身的聪明做法 --- 我看电视剧《雍正王朝》
  • 原文地址:https://www.cnblogs.com/Answer1215/p/7351191.html
Copyright © 2020-2023  润新知