如何在多个组件

时间:2016-08-15 07:00:06

标签: angular ionic2 angular2-components angular2-formbuilder

我正在尝试在Ionic 2的页面中使用FormBuilder。

首先,这是我的环境细节: 在Windows 10上运行,并运行 ionic --version 给我 2.0.0-beta.35

以下是 package.json 文件的一部分:

...
"@angular/common": "2.0.0-rc.3",
"@angular/compiler": "2.0.0-rc.3",
"@angular/core": "2.0.0-rc.3",
"@angular/forms": "^0.3.0",
"@angular/http": "2.0.0-rc.3",
"@angular/platform-browser": "2.0.0-rc.3",
"@angular/platform-browser-dynamic": "2.0.0-rc.3",
"ionic-angular": "2.0.0-beta.10",
"ionic-native": "1.3.2",
"ionicons": "3.0.0"
...

其次,这是涉及的两个主要文件:

insight.ts

import { Component } from '@angular/core';
import {NavController, NavParams} from 'ionic-angular';
import {
  REACTIVE_FORM_DIRECTIVES,
  FormBuilder,
  FormControl,
  FormGroup
} from '@angular/forms';
import { App, Insight } from '../../models';
import { InsightProvider } from '../../providers/insight/insight.service';
import { InsightImage, InsightLabel, InsightLink, InsightQuestion, InsightThought, InsightTodo, InsightVideo } from './shared';

@Component({
  templateUrl: 'build/pages/insight/insight.html',
  directives: [REACTIVE_FORM_DIRECTIVES, InsightImage, InsightLabel, InsightLink, InsightQuestion, InsightThought, InsightTodo, InsightVideo],
  providers: [App, InsightProvider, FormBuilder]
})
export class InsightPage {

  canAdd: boolean;
  showDetails: boolean;
  newInsight: Insight;
  insightForm: FormGroup;

  constructor(private insightProvider: InsightProvider,
              private params: NavParams) {
    this.insightForm = new FormGroup({
      type: new FormControl('', []),
      todo: new FormControl('', []),
      checked: new FormControl(false, []),
      imageUrl: new FormControl('', []),
      link: new FormControl('', []),
      url: new FormControl('', []),
      label: new FormControl('', []),
      question: new FormControl('', []),
      answer: new FormControl('', []),
      title: new FormControl('', []),
      details: new FormControl('', []),
    });
  }

  ngOnInit() {
    this.canAdd = false;
    this.showDetails = true;
  }

  addNewInsight() {
    if (this.newInsight.type) {
      this.insightProvider.createInsight(this.newInsight)
      .subscribe(response => {
        this.newInsight.setId(response.data.id);
        this.newInsight.title = '';
        console.log(response);
      });
    }
  }

  deleteClicked(index: number) {
    console.log('Clicked on ' + index);
    this.insightProvider.deleteInsight(this.newInsight)
    .subscribe(data => {
      console.log(data);
    });
  }


}

insight.html

<form [ngFormModel]="insightForm" (ngSubmit)="createNewInsight()">
      <ion-item>
        <ion-label for="type">Insight Type</ion-label>
        <ion-select name="type" id="type" [formControl]="type">
          <ion-option value="label">Label</ion-option>
          <ion-option value="thought">Thought</ion-option>
          <ion-option value="link">Link</ion-option>
          <ion-option value="question">Question</ion-option>
          <ion-option value="todo">Todo</ion-option>
          <ion-option value="image">Image</ion-option>
          <ion-option value="video">Video</ion-option>
        </ion-select>
      </ion-item>

      <div [ngSwitch]="type">
          <insight-image [form]="insightForm" *ngSwitchCase="'image'"></insight-image>
          <insight-label [form]="insightForm" *ngSwitchCase="'label'"></insight-label>
          <insight-link [form]="insightForm" *ngSwitchCase="'link'"></insight-link>
          <insight-question [form]="insightForm" *ngSwitchCase="'question'"></insight-question>
          <insight-thought [form]="insightForm" *ngSwitchCase="'thought'"></insight-thought>
          <insight-todo [form]="insightForm" *ngSwitchCase="'todo'"></insight-todo>
          <insight-video [form]="insightForm" *ngSwitchCase="'video'"></insight-video>
      </div>

      <button type="submit" block primary text-center (click)="addNewInsight()" [disabled]="!newInsight.type">
        <ion-icon name="add"></ion-icon> Add Insight
      </button>
    </form>

正如您所看到的,我正在尝试将FormGroup对象传递给多个组件,以便我可以使用它们。

以下是其中一个组件的示例(现在是最小版本):

<ion-item>
  <ion-label floating for="link">Link</ion-label>
  <ion-input type="text" name="link" id="link" [formControl]="link"></ion-input>
</ion-item>

<ion-item>
  <ion-label floating for="url">URL</ion-label>
  <ion-input type="text" id="url" name="url" [formControl]="url"></ion-input>
</ion-item>

我现在面临的问题是这个错误:

Error from FormBuilder and Ionic 2

我相信发生的事情是FormBuilder正在寻找我在我的打字稿文件中声明的给定名称(例如todo,imageUrl,link等),但由于它在我的其他组件中,它会出错,思考它不存在。

出现此错误的原因是什么?我看过网上找不到相关问题。

仅供参考,我在组件中而不是在同一页面中需要它们的原因是因为将来每个输入的功能都不同,因此需要为每个组件提供“单一责任”。

提前致谢

3 个答案:

答案 0 :(得分:20)

对于其他每个有问题的人

  

找不到具有未指定名称属性的控件。

问题是您忘记在表单输入元素上定义formControlName

formControlName="url"

如果您在修复输入后面临No provider for NgControl,那么Ionic2在Fom处理方面的变化就会出现问题。您可以通过导入新的表单组件来修复代码:

import { disableDeprecatedForms, provideForms } from '@angular/forms';

但你可能仍会面临越来越多的问题。要真正修复您的代码:

  • 更新到最新的测试版
  • 将表单简化为2个简单输入
  • 重写表单并使其正常工作
  • 添加其余元素

关于FormBuilder和验证的好教程 https://blog.khophi.co/ionic-2-forms-formbuilder-and-validation/

答案 1 :(得分:3)

作为Angular 2+的一般说明,我发现采用一致的方法来指定formGroupName,formArrayName和formGroupNamesaved大量的时间,以及我的理智仍然是什么。在我做之前我失去了很多时间。

使用

formXXXName="literal value"

formXXXName="{{value expression}}"

或者

[formXXXName]="'literal value'" (single tick within double tick)

[formXXXName]="value expression"

我一直在混淆他们,让我感到非常悲伤。

最近项目的示例:

案例1:正确使用括号表示法。

    <label>Notes</label>
    <div class="panel panel-default">
        <div class="panel-body">
            <div [formArrayName]="'notes'">
                <div *ngFor="let note of outletForm.controls.notes.controls; let i=index">
                    <input type="text" [formControlName]="i" class="form-control" />
                </div>
            </div>
        </div>
    </div>

案例2:正确使用非括号表示法。

    <label>Notes</label>
    <div class="panel panel-default">
        <div class="panel-body">
            <div formArrayName="notes">
                <div *ngFor="let note of outletForm.controls.notes.controls; let i=index">
                    <input type="text" formControlName="{{i}}" class="form-control" />
                </div>
            </div>
        </div>
    </div>

请注意上面使用&#34; {{&#34;和&#34;}}&#34;强迫Angular将通常的文字字符串值(因为使用无括号语法)视为EL表达式。

案例3:使用括号表示法不正确

    <label>Notes</label>
    <div class="panel panel-default">
        <div class="panel-body">
            <div [formArrayName]="notes">
                <div *ngFor="let note of outletForm.controls.notes.controls; let i=index">
                    <input type="text" formControlName="{{i}}" class="form-control" />
                </div>
            </div>
        </div>
    </div>

在这种情况下,formArrayName,&#34; notes&#34;的值被视为EL表达式。由于我的组件没有这样的成员,因此它的评估结果为空。因此,持续存在以下错误:

OutletFormComponent.html:153 ERROR Error: Cannot find control with unspecified name attribute
    at _throwError (forms.es5.js:1830)
    at setUpFormContainer (forms.es5.js:1803)
    at FormGroupDirective.addFormArray (forms.es5.js:4751)
    at FormArrayName.ngOnInit (forms.es5.js:5036)
    at checkAndUpdateDirectiveInline (core.es5.js:10793)
    at checkAndUpdateNodeInline (core.es5.js:12216)
    at checkAndUpdateNode (core.es5.js:12155)
    at debugCheckAndUpdateNode (core.es5.js:12858)
    at debugCheckDirectivesFn (core.es5.js:12799)
    at Object.eval [as updateDirectives] (OutletFormComponent.html:159)

幸运的是,堆栈最底部给出的行号指向有问题的行。

案例4:错误使用非包围符号

    <label>Notes</label>
    <div class="panel panel-default">
        <div class="panel-body">
            <div [formArrayName]="'notes'">
                <div *ngFor="let note of outletForm.controls.notes.controls; let i=index">
                    <input type="text" formControlName="i" class="form-control" />
                </div>
            </div>
        </div>
    </div>

在这种情况下,formControlName,&#34; i&#34;的值将被解释为文字字符串,但我们真的打算引用索引变量&#39; i&#39;在contains * ngFor指令上。此错误的结果是:

OutletFormComponent.html:161 ERROR Error: Cannot find control with path: 'notes -> i'
    at _throwError (forms.es5.js:1830)
    at setUpControl (forms.es5.js:1738)
    at FormGroupDirective.addControl (forms.es5.js:4711)
    at FormControlName._setUpControl (forms.es5.js:5299)
    at FormControlName.ngOnChanges (forms.es5.js:5217)
    at checkAndUpdateDirectiveInline (core.es5.js:10790)
    at checkAndUpdateNodeInline (core.es5.js:12216)
    at checkAndUpdateNode (core.es5.js:12155)
    at debugCheckAndUpdateNode (core.es5.js:12858)
    at debugCheckDirectivesFn (core.es5.js:12799)

感谢所有Angular2 +开发人员和专家。

答案 2 :(得分:0)

使用FormBuilder时,在模板中必须定义控件,以便FormBuilder识别控件。

所以在你的模板中有一个名为&#39; insightForm&#39;的formGroup。使用控件&#39; <#39;:

<form [formGroup]="insightForm" (ngSubmit)="onSubmit(insightForm.value)">
    <ion-input [formControl]="insightForm.controls['url']"></ion-input>
</form>