2016-08-15 26 views
7

Próbuję użyć FormBuilder na stronie mam w jońskich 2.Jak korzystać kątowa 2 za FormBuilder między wieloma komponentami

pierwsze, tutaj jest moje dane środowiskowe: w systemie Windows 10, a uruchomione jonowe - -version daje mi 2.0.0-beta.35

Tutaj jest częścią mojego package.json pliku:

... 
"@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" 
... 

drugie, tu są dwa główne pliki zaangażowane:

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> 

Jak widać, staram się przekazać FormGroup Object na wiele komponentów, aby móc z nich korzystać.

Oto przykład tego, co jeden ze składników wyglądać (minimalna wersja teraz):

<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> 

Problem jestem stoi teraz jest ten błąd:

Error from FormBuilder and Ionic 2

Wierzę, że dzieje się tak, że FormBuilder szuka podanych przeze mnie nazw w moim pliku maszynopisowym (takich jak todo, imageUrl, link itp.), Ale ponieważ jest w moich innych komponentach, to pomyłki, myśląc, że tam nie ma .

Co może być przyczyną tego błędu? Sprawdziłem online i nie mogłem znaleźć pokrewnych problemów.

FYI, powód, dla którego potrzebuję ich w komponentach, a nie na tej samej stronie, jest taki, że w przyszłości funkcjonalność będzie różna dla każdego wejścia, w związku z czym konieczne jest nadanie każdemu elementowi "Pojedynczej odpowiedzialności".

góry dzięki

+0

nie wspomniałeś wersję Ionic2 używasz, może to być ważne. Nie jestem pewien, ale błąd mówi "nieokreślona nazwa", więc spróbuj użyć 'ngControl =" url "' zamiast '[formControl] =" url "' – dafyk

+0

Właśnie zaktualizowałem moje pytanie, aby umieścić na górze moje szczegóły dotyczące środowiska. Dziękuję, że przypomniałeś mi, że dałeś ci znać o moim środowisku. Próbowałem ngControl = "url", ale otrzymuję teraz "Brak dostawcy dla ControlContainer". Dodałem "ControlContainer" jako dostawcę w moim komponencie, ale otrzymałem ten sam błąd. Na wszelki wypadek próbowałem zrobić formControl = "url" Otrzymałem ten sam błąd –

+1

Cóż Ionic2 wciąż jest w wersji beta, oczekuj pewnych zmian przełomowych zgodnie z [Forms Upcoming Change Proposal] (https://docs.google.com/document/u/1/d/1RIezQqE4aEhBRmArIAS1mRIZtFf6JxN_7B4meyWK0Y/pub). Moje następne przypuszczenie jest użycie 'formControlName =" url "' – dafyk

Odpowiedz

20

Dla każdego innego z problemem

Cannot find control with unspecified name attribute.

Problem zapomniałeś określić formControlName na swoich elementów wejściowych formularza.

formControlName="url"

Jeśli stoją No provider for NgControl po wejść ustalające masz problem z Ionic2 łamanie zmian w obsłudze FOM. Jest szansa, można naprawić swój kod importując nowy składnik forma:

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

Ale prawdopodobnie będzie nadal napotykają coraz więcej problemów.Aby naprawdę naprawić swój kod:

  • aktualizację do najnowszej wersji beta
  • uprościć formularz do 2 prostych wejść
  • przepisać swoją formę i sprawiają, że działa
  • dodać resztę swoich elementów

Dobry samouczek dotyczący FormBuilder i sprawdzania poprawności https://blog.khophi.co/ionic-2-forms-formbuilder-and-validation/

+4

Dzięki! Używałem '[formControlName] =" url "' zamiast 'formControlName =" url "' – Kevin

+0

To samo co powyżej, dziękuję za to. – Arg0n

+0

Jeśli używasz formArrays, musisz podać nazwę w 'formArrayName =" name "' w div otaczającym twoją pętlę * ngFor, która drukuje wiele formularzy – triadiktyo

3

Jako ogólna uwaga w Angular 2+, stwierdziłem, że przyjęcie spójnego podejścia do określania formGroupName, formArrayName i formGroupNamesaved dużo czasu i co pozostało z mojego zdrowia psychicznego. Straciłem dużo czasu, zanim to zrobiłem.

Albo użyć

formXXXName="literal value" 

Albo

formXXXName="{{value expression}}" 

Albo

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

Albo

[formXXXName]="value expression" 

ja wa ciągle ich mieszam, ku mojemu wielkiemu smutkowi.

Przykład z ostatnim projekcie:

Przypadek 1: Prawidłowe stosowanie notacji zamka.

<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> 

Przypadek 2: Prawidłowe użycie notacji nie-nawiasowych.

<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> 

Proszę zwrócić uwagę w powyższym zastosowaniu „{{” i „}}”, aby zmusić kątowa do leczenia, co normalnie byłoby dosłowną wartość ciągu (z powodu użycia składni bez uchwytów) jako wyrażenie EL.

Przypadek 3: Nieprawidłowe wykorzystanie notacji wspornika

<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> 

W tym przypadku, wartość formArrayName, "Notes", jest traktowana jako wyraz EL. Ponieważ mój komponent nie ma takiego elementu, ocenia się na nic. Dlatego następujący błąd jest trwały:

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) 

szczęście, numer linii podany na samym dole stosu punktów do linii z problemem.

Przypadek 4: Nieprawidłowe korzystanie z nieprzestrzegania bracketingu notacji

<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> 

W tym przypadku, wartość formControlName, „i”, będzie interpretowane jako dosłownego łańcucha, ale naprawdę ma odnosić się do zmienna indeksowa "i" w dyrektywie zawierającej * ngFor.Wynik tego błędu:

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) 

Dzięki i kudos dla wszystkich programistów i ekspertów Angular2 +.

0

Podczas korzystania z FormBuilder, w szablonie należy zdefiniować formant, aby FormBuilder mógł zidentyfikować formant.

Więc w szablonie, który ma formGroup nazwie „insightForm” z kontroli „url”:

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