angular2 rc.5 нестандартне введення, немає доступу до значення для керування формою з невстановленим іменем


80

У мене є такий простий компонент вводу, як цей,

import {Component, Provider, forwardRef} from "@angular/core";
import {ControlValueAccessor, NG_VALUE_ACCESSOR} from "@angular/forms";

const noop = () => {};

const CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR: any = {
  provide: NG_VALUE_ACCESSOR,
  useExisting: forwardRef(() => CustomInputComponent),
  multi: true
};

@Component({
  selector: 'custom-input',
  template: `

          <input class="form-control" 
                 [(ngModel)]="value" name="somename"
                 (blur)="onTouched()">

  `,
  providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
})
export class CustomInputComponent implements ControlValueAccessor{

  //The internal data model
  private _value: any = '';

  //Placeholders for the callbacks
  private _onTouchedCallback: () => void = noop;

  private _onChangeCallback: (_:any) => void = noop;

  //get accessor
  get value(): any { return this._value; };

  //set accessor including call the onchange callback
  set value(v: any) {
    if (v !== this._value) {
      this._value = v;
      this._onChangeCallback(v);
    }
  }

  //Set touched on blur
  onTouched(){
    this._onTouchedCallback();
  }

  //From ControlValueAccessor interface
  writeValue(value: any) {
    this._value = value;
  }

  //From ControlValueAccessor interface
  registerOnChange(fn: any) {
    this._onChangeCallback = fn;
  }

  //From ControlValueAccessor interface
  registerOnTouched(fn: any) {
    this._onTouchedCallback = fn;
  }

}

і у мене є такий модуль додатків,

/**
 * Created by amare on 8/15/16.
 */
import { NgModule }                     from '@angular/core';
import { BrowserModule }                from '@angular/platform-browser';
import { ReactiveFormsModule, FormsModule }          from '@angular/forms';
import { AppComponent }                 from './app/app.component';
import {CustomInputComponent} from "./app/shared/custom.input.component";
import {RouterModule} from "@angular/router";
@NgModule({
  imports: [ BrowserModule, ReactiveFormsModule, FormsModule, RouterModule ],
  declarations: [ AppComponent, CustomInputComponent],
  bootstrap: [ AppComponent ]
})
export class AppModule {  
}

і основний

import { platformBrowserDynamic } from '@angular/platform-browser-dynamic';
import { AppModule }              from './app.module';

platformBrowserDynamic().bootstrapModule(AppModule);

і я використав свій власний ввід в одному зі своїх компонентів, як показано нижче, але отримую "Немає доступу до значення для керування формою з невизначеним атрибутом імені".

<custom-input name="firstName" [(ngModel)]="firstName"></custom-input>

а app.component виглядає так

import { Component } from '@angular/core';

@Component({
  moduleId: module.id,
  selector: 'app-root',
  templateUrl: 'app.component.html',
  styleUrls: ['app.component.css']
})
export class AppComponent {
  title = 'app works!';

  firstName: string;
}

У мене така ж проблема з користувацькою директивою, яка реалізує ControlValueAccessor. Він працював у RC4, але отримує таку ж помилку, як і у RC5. Сподіваючись, хтось має рішення.
user2444499

38
Спробуйте додати ngDefaultControlдо свого контролю, ось так:<custom-input name="firstName" [(ngModel)]="firstName" ngDefaultControl></custom-input>
danieleds

@danieleds дякую, це працює як шарм, навіть незважаючи на те, що команда не відповідає.
Амаре

1
Остерігайтеся будь-яких сторонніх пакетів, якими ви можете користуватися - якщо ви імпортуєте щось, що використовує старе FORM_DIRECTIVES, це зламає вашу програму! Справа в справі: github.com/valor-software/ng2-charts/issues/352
Піт,

Для мене додавання ngDefaultControl до того, як [(ngModel)] = "...." спрацювало
themightysapien

Відповіді:


73

Додавання ngDefaultControl до користувацького вхідного компонента на хості вирішило проблему, завдяки @danieleds


8
Це рішення для мене не спрацювало. У мене є ім’я, застосоване до мого, inputі я також спробував додати ngDefaultControlдо вводу, і це не спрацювало. Все-таки дав мені ту ж помилку. У RC5
prolink007

2
Погодьтеся, я додав властивість name у html та ngDefaultControl, і я використовую formControl, і це не працює.
Steve K

1
Дивіться дуже гарне пояснення того, як це ngDefaultControlпрацює - stackoverflow.com/a/46465959/968003 . По суті, він додає за замовчуванням ControlValueAccessor, який діє як міст між API Angular форм і власним елементом у DOM.
Алекс Клаус,

46

Додайте ngDefaultControl до користувацького компонента введення. Це додає двосторонню прив'язку даних, вам не доведеться реалізовувати методи доступу до значень, якщо ви не робите щось унікальне.

<custom-input name="firstName" [(ngModel)]="firstName" ngDefaultControl></custom-input>

12

Додайте ngDefaultControlдо свого вводу. напр

<inline-editor type="textarea" [(ngModel)]="editableTextArea" (onSave)="saveEditable($event)" value="valor" ngDefaultControl> </inline-editor> 

Тоді import { FORM_DIRECTIVES } from '@angular/common';

Нарешті, директиви: [FORM_DIRECTIVES]

Це спрацює :) Дякую за наведені вище коментарі


2
Будь ласка, використовуйте зворотні позначки та інші markdownкоманди, щоб зробити вашу публікацію зручнішою для читання.
buhtz

4
Я використовую RC6 і немає FORM_DIRECTIVESв@angular/common
Kosmonaft

6
ФОРМОВІ ДИРЕКТИВИ НЕ БІЛЬШІ З NG2 FINAL
Steve K

4

Я укладав [(ngModel)]на моєму <option>тезі замість<select>

Так так ... це спричинить це.


Так .... У мене виникла та сама помилка, коли я поставив ngModel на <mat-radio-button>, а не на <mat-radio-group>. Grrrrrr ....
Mike

0

Як ще один сценарій, коли це виникає, я [(ngModel)]вказав спеціальний компонент, який нещодавно був відновлений та спрощений, а нова версія компонента просто мала ngModelзвичайну вхідну змінну з випромінюванням.

Цього було недостатньо - вхідну змінну потрібно перейменовувати на щось крім того ngModel, або компонент повинен реалізовувати ControlValueAccessorінтерфейс (детальніше див. Документи ). Як тільки одне чи інше буде завершено, ви більше не отримуватимете цієї помилки.

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.