代码之家  ›  专栏  ›  技术社区  ›  firegloves

角6反应形式精选系列

  •  1
  • firegloves  · 技术社区  · 6 年前

    我跟着 Angular Reative Form guide 这就解释了如何将一系列adrress添加到formgroup中。

    现在我想有一个英雄可以有不同的力量,从 select ,或者更好地从 选择 是的。

    从角度文档的例子到我想要的功能,我不能让它运行。

    这是我的英雄表

    @Component({
      selector: 'app-hero-form',
      templateUrl: './hero-form.component.html',
      styleUrls: ['./hero-form.component.css']
    })
    export class HeroFormComponent implements OnInit, OnChanges {
    
      heroForm: FormGroup;
      nameChangeLog: string[] = [];
      hero: Hero = new Hero();
      allPowers: Power[] = [];
    
      constructor(private fb: FormBuilder, private powerService: PowerService) {
        this.createForm();
        this.logNameChange();
      }
    
      ngOnInit() {
        this.powerService.getAll().subscribe(powers => this.allPowers = powers);
      }
    
      createForm() {
        this.heroForm = this.fb.group({
          name: ['', Validators.required],
          powers: this.fb.array([]),
        });
      }
    
      ngOnChanges() {
        this.rebuildForm();
      }
    
      rebuildForm() {
        this.heroForm.reset({
          name: this.hero.name
        });
        this.setPowersControl(this.hero.powers);
      }
    
      setPowersControl(powers: Power[]) {
        const powersFGs = powers.map(pow => this.fb.group(pow));
        const powersFormArray = this.fb.array(powersFGs);
        this.heroForm.setControl('powers', powersFormArray);
      }
    
    
      get powers(): FormArray {
        const pows = this.heroForm.get('powers') as FormArray;
        return pows;
      }
    
    
      addPowerChoice() {
        this.powers.push(this.fb.control(new Power()));
        // this.powers.push(this.fb.group(new Power(), Validators.required));
      }
    
      onSubmit() {
        this.hero = this.prepareSaveHero();
        console.log('SAVING HERO', this.hero);
        // this.heroService.updateHero(this.hero).subscribe(/* error handling */);
        this.rebuildForm();
      }
    
      prepareSaveHero(): Hero {
        const formModel = this.heroForm.value;
    
        // deep copy of form model lairs
        const powersDeepCopy: Power[] = formModel.powers.map(
          (pow: Power) => Object.assign({}, pow)
        );
    
        // return new `Hero` object containing a combination of original hero value(s)
        // and deep copies of changed form model values
        const saveHero: Hero = {
          id: this.hero.id,
          name: formModel.name as string,
          // addresses: formModel.secretLairs // <-- bad!
          powers: powersDeepCopy
        };
        return saveHero;
      }
    
      revert() { this.rebuildForm(); }
    
      logNameChange() {
        const nameControl = this.heroForm.get('name');
        nameControl.valueChanges.forEach(
          (value: string) => this.nameChangeLog.push(value)
        );
      }
    
    }
    

    这是我的hero-form.html

    <form [formGroup]="heroForm" (ngSubmit)="onSubmit()">
        <div style="margin-bottom: 1em">
            <button type="submit" [disabled]="heroForm.pristine" class="btn btn-success">Save
            </button> &nbsp;
            <button type="button" (click)="revert()" [disabled]="heroForm.pristine" class="btn btn-danger">Revert</button>
        </div>
    
        <!-- Hero Detail Controls -->
        <div class="form-group">
            <label class="center-block">Name:
                <input class="form-control" formControlName="name">
            </label>
        </div>
    
        <div formArrayName="powers" class="well well-lg">
            <div *ngFor="let pow of powers.controls; let i=index" [formControlName]="i">
                <!-- The repeated power template -->
                <h4>Potere #{{i + 1}}</h4>
                <div style="margin-left: 1em;">
    
                    <div class="form-group">
                        <label class="center-block">Power:
                            <select class="form-control">
                                <option *ngFor="let pow of allPowers" [value]="pow">{{pow.name}}</option>
                            </select>
                        </label>
                    </div>
    
                </div>
                <br>
                <!-- End of the repeated address template -->
            </div>
            <button (click)="addPowerChoice()" type="button">Add a Power</button>
        </div>
    
    </form>
    
    <p>heroForm value: {{ heroForm.value | json}}</p>
    
    <h4>Name change log</h4>
    <div *ngFor="let name of nameChangeLog">{{name}}</div>
    

    这是只返回存根数据的电力服务

    @Injectable({
      providedIn: 'root'
    })
    export class PowerService {
    
      constructor() {
      }
    
      getAll(): Observable<Power[]> {
        return of(this.getProds());
      }
    
      getProds(): Power[] {
        const powers = [];
        for (let i = 0; i < 10; i++) {
          const pow = new Power();
          pow.id = i+'';
          pow.name = 'Power ' + i;
          powers.push(pow);
        }
        return powers;
      }
    }
    

    这些是我的数据模型

    export class Hero {
      id: number;
      name: string;
      powers: Power[];
    }
    
    export class Power {
      id: string = '';
      name: string = '';
    }
    

    在这里我做了一个 stackblitz example 但没用

    1 回复  |  直到 5 年前
        1
  •  1
  •   firegloves    6 年前

    我已经解决了

    我已经搬家了 formControlName div 到上面 select 按照卢卡斯·克拉森的建议 [value] [ngValue] 到上面 option

    <form [formGroup]="heroForm" (ngSubmit)="onSubmit()">
      <div style="margin-bottom: 1em">
        <button type="submit"
                [disabled]="heroForm.pristine" class="btn btn-success">Save
        </button> &nbsp;
        <button type="button" (click)="revert()"
                [disabled]="heroForm.pristine" class="btn btn-danger">Revert
        </button>
      </div>
    
      <!-- Hero Detail Controls -->
      <div class="form-group">
        <label class="center-block">Name:
          <input class="form-control" formControlName="name">
        </label>
      </div>
    
      <div formArrayName="powers" class="well well-lg">
        <div *ngFor="let pow of powers.controls; let i=index">
          <!-- The repeated power template -->
          <h4>Potere #{{i + 1}}</h4>
          <div style="margin-left: 1em;">
    
            <div class="form-group">
              <label class="center-block">Power:
                <select class="form-control" [formControlName]="i">
                  <option *ngFor="let pow of allPowers" [ngValue]="pow">{{pow.name}}</option>
                </select>
              </label>
            </div>
    
          </div>
          <br>
          <!-- End of the repeated address template -->
        </div>
        <button (click)="addPowerChoice()" type="button">Add a Power</button>
      </div>
    
    </form>
    
    <p>heroForm value: {{ heroForm.value | json}}</p>
    
    <h4>Name change log</h4>
    <div *ngFor="let name of nameChangeLog">{{name}}</div>
    

    那我就变了 onSubmit() 添加英雄的构造函数调用,如下所示

    onSubmit() {
        this.hero = this.prepareSaveHero();
        console.log('SAVING HERO', this.hero);
        // this.heroService.updateHero(this.hero).subscribe(/* error handling */);
        this.hero = new Hero();
        this.rebuildForm();
    }
    

    然后我添加了一个自定义构造函数 Hero

    export class Hero {
      id: number;
      name: string;
      powers: Power[];
    
      constructor() {
        this.id = 0;
        this.name = '';
        this.powers = [];
      }
    }
    

    现在它可以正常工作了,提交后可以正确地重建表单

    推荐文章