Angular 2 form.value属性未定义

本杰明·巴金斯(Benjamin Baggins)

我试图在自定义控件上首次使用name[(ngModel)]模板驱动的表单语法,该控件使用的controlValueAccessor也是我第一次使用的。

当我在其中输入一些单词,<input>然后将其登录form.value到控制台时,我看到添加的表单字段的名称,但仍未定义:

Object {keywords: undefined}

如果我以编程方式为result.keywords设置一个值,那么当我将form.value记录到控制台时,将填充keyword属性。从模型到form.value的绑定正在工作。从视图(html输入控件)到模型的绑定无效。

ngOnInit() {
    this.result = new Result();
    this.result.keywords = ["aaa"]; <----works
}

上面将在控制台中显示[“ aaa”],但在视图中将不显示任何内容。如何正确获取要填充的表单的keywords属性?

我的代码:

我的表格:

 <form class="text-uppercase" (ngSubmit)="onSubmit(findForm.value, findForm.valid)" #findForm="ngForm">
        <vepo-input 
           [placeholder]='"keywords (optional)"' 
           [id]='"keywordsInput"'
           name="keywords"
           [(ngModel)]="result.keywords">
        </vepo-input>
    </form>

input-component.ts:

import { Component, ViewChild, ElementRef, Input, forwardRef } from '@angular/core';
import { NG_VALUE_ACCESSOR, ControlValueAccessor } from '@angular/forms';

const noop = () => {
};

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


@Component({
    selector: 'vepo-input',
    templateUrl: 'app/shared/subcomponents/input.component.html',
    styleUrls: ['app/shared/subcomponents/input.component.css'],
    providers: [CUSTOM_INPUT_CONTROL_VALUE_ACCESSOR]
})

export class InputComponent implements ControlValueAccessor {
    @Input() private placeholder: string;
    @Input() private id: string;

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

    //Placeholders for the callbacks which are later providesd
    //by the Control Value Accessor
    private onTouchedCallback: () => void = noop;
    private onChangeCallback: (_: any) => void = noop;

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

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

    //Set touched on blur
    onBlur() {
        this.onTouchedCallback();
    }

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

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

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

}

input.component.html:

<input  class="form-item-input"
            placeholder={{placeholder}} 
            id={{id}} />
<label   attr.for="{{id}}"
         class="form-item-right-icon input-icon">
</label>

我的表单实际上比我发布的表单大很多,但是我不想让所有人不相关的代码超载。为了完整起见,这里是完整的form.ts文件:

import {
    Component,
    ViewChild,
    ElementRef,
    EventEmitter,
    Output,
    OnInit
} from '@angular/core';
import {
    FormGroup,
    FormBuilder,
    Validators,
    ControlValueAccessor
} from '@angular/forms';
import { ResultService } from '../../../services/result.service';
import { Result } from '../../../models/all-models';
import { HighlightDirective } from '../../../directives/highlight.directive';
import { DistanceUnitsComponent } from './distance-units.component';
import { MultiselectComponent } from './multiselect-find-category.component';
import { MultiselectFindMealTypeComponent } from
    './multiselect-find-meal-type.component';
import { AreaComponent } from './area-picker.component';
import { NumberPickerComponent } from './number-picker.component';
import { InputComponent } from '../../../shared/subcomponents/input.component';

@Component({
    selector: 'find-form',
    templateUrl: 'app/find-page/subcomponents/find-page/find-form.component.html',
    styleUrls: ['app/find-page/subcomponents/find-page/find-form.component.css'],
    providers: [ResultService]
})
export class FindFormComponent implements OnInit {

    @ViewChild('multiselectFindCategory')
    private multiselectFindCategory: MultiselectComponent;
    @ViewChild('multiselectFindMealType')
    private multiselectFindMealType: MultiselectFindMealTypeComponent;
    @ViewChild('distanceUnits') private distanceUnits: DistanceUnitsComponent;
    @ViewChild('numberPicker') private numberPicker: NumberPickerComponent;
    @ViewChild('areaInput') private areaInput: AreaComponent;
    @ViewChild('keywordsInput') private keywordsInput: InputComponent;

    @Output() private onResultsRecieved:
    EventEmitter<Object> = new EventEmitter<Object>();
    @Output() private onSubmitted: EventEmitter<boolean> =
    new EventEmitter<boolean>();

    private categoryError: string = 'hidden';
    private mealTypeError: string = 'hidden';
    private areaError: string = 'hidden';

    private findForm: FormGroup;
    private submitted: boolean = false;
    private result: Result;

    private displayMealCategories: boolean = false;
    private mealSelected: boolean = false;
    private place: google.maps.Place;

    constructor(private resultService: ResultService,
        private formBuilder: FormBuilder,
        el: ElementRef) { }

    ngOnInit() {
        this.result = new Result();
    }

    private setCategoryErrorVisibility(
        multiselectFindCategory: MultiselectComponent
    ): void {
        if (multiselectFindCategory.selectedCategories.length < 1 &&
            !multiselectFindCategory.allSelected &&
            this.submitted) {
            this.categoryError = 'visible';
        } else {
            this.categoryError = 'hidden';
        }
    }

    private setMealTypeErrorVisibility(
        multiselectFindMealType: MultiselectFindMealTypeComponent
    ): void {
        if (multiselectFindMealType) {
            if (multiselectFindMealType.selectedCategories.length < 1 &&
                !multiselectFindMealType.allSelected &&
                this.submitted) {
                this.mealTypeError = 'visible';
            } else {
                this.mealTypeError = 'hidden';
            }
        }
    }

    private setAreaErrorVisibility(): void {
        if (this.areaInput.areaInput.nativeElement.value) {
            if (!this.areaInput.address) {
                this.areaError = 'visible';
                this.areaInput.areaInput.nativeElement.setCustomValidity("Please select from dropdown or leave blank.");
            } else {
                this.areaError = 'hidden';
                this.areaInput.areaInput.nativeElement.setCustomValidity("");
            }
        } else {
            this.areaError = 'hidden';
            this.areaInput.areaInput.nativeElement.setCustomValidity("");
        }
    }

    private onCategoriesChanged(): void {
        this.setCategoryErrorVisibility(this.multiselectFindCategory);
        this.mealSelected = this.multiselectFindCategory.mealSelected;
        if (!this.mealSelected) {
            this.mealTypeError = 'hidden';
        }
    }

    private onMealTypesChanged(): void {
        this.setMealTypeErrorVisibility(this.multiselectFindMealType);
    }

    private onAreaChanged(areaEntered: any): void {
        this.setStateOfDistanceControls(areaEntered.areaEntered);
        this.areaError = "hidden";
        this.areaInput.areaInput.nativeElement.setCustomValidity("");
        if (areaEntered.place) {
            this.place = areaEntered.place;
        }
    }

    private setStateOfDistanceControls(areaEntered: any): void {
        if (areaEntered.areaEntered) {
            this.distanceUnits.isEnabled = true;
            this.numberPicker.isEnabled = true;
        } else {
            this.distanceUnits.isEnabled = false;
            this.numberPicker.isEnabled = false;
        }
        this.distanceUnits.setImage();
    }

    private getResults(): void {
        var results: Result[] = [];
        results = this.resultService.getResults();
        if (results) {
            this.onResultsRecieved.emit({
                recieved: true,
                results: results,
                place: this.place
            });
        }
    }

    private onSubmit(model: any, isValid: boolean): void {

        console.log(model, isValid);


        // this.submitted = true;
        // this.setCategoryErrorVisibility(this.multiselectFindCategory);
        // this.setMealTypeErrorVisibility(this.multiselectFindMealType);
        // this.setAreaErrorVisibility();
        // if (this.areaError === "hidden" &&
        //  this.categoryError === "hidden" &&
        //  this.mealTypeError === "hidden") {
        //  this.onSubmitted.emit(true);
        //  this.getResults();
        // }
    }
}
沉默寡言

好吧,这是我与一个正在工作的小伙子备份工作的意图:

在您的input.component.html中,您需要确保已将绑定设置为ngModel

<input class="form-item-input" [(ngModel)]="value" [placeholder]="placeholder" id="{{id}}" />

除此之外,实际上没有其他事情可做。

这是the客:http ://plnkr.co/edit/HleTVBnvd8ePgMClAZS2?p=preview

本文收集自互联网,转载请注明来源。

如有侵权,请联系[email protected] 删除。

编辑于
0

我来说两句

0条评论
登录后参与评论

相关文章

来自分类Dev

属性未定义的Angular2和TypeScript

来自分类Dev

Angular 2-组件属性在方法中未定义

来自分类Dev

无法读取未定义Angular 2的属性

来自分类Dev

Angular 2 ngFor访问属性时未定义

来自分类Dev

Angular - Ionic 2 - 无法读取未定义的属性“订阅”

来自分类Dev

(Angular2 和 Typescript)Angular 的 DatePicker 无法读取未定义的属性“切换”

来自分类Dev

NgZone / Angular2 / Ionic2 TypeError:无法读取未定义的属性“运行”

来自分类Dev

Angular 2 Component全局变量在Reactive Form控制器valueChanges事件中未定义

来自分类Dev

Angular2-未定义OnInit

来自分类Dev

Angular2'this'未定义

来自分类Dev

Angular 2 ContentChild未定义

来自分类Dev

参数未定义的 Angular 2 路由

来自分类Dev

Angular 2 this.data 未定义

来自分类Dev

Angular2-TypeError:无法读取(Typescript)中未定义的属性'Id'

来自分类Dev

无法读取Angular 2中的嵌套调用中未定义的属性“ subscribe”

来自分类Dev

Angular2 * ngFor:“无法读取未定义的属性'0'”

来自分类Dev

Angular 2异常:TypeError:无法读取未定义的属性“ annotations”

来自分类Dev

Angular 2 ViewChild不起作用-无法读取未定义的属性nativeElement

来自分类Dev

Webpacked Angular2应用程序TypeError:无法读取未定义的属性“ getOptional”

来自分类常见问题

Angular2 IE11无法获取未定义或空引用的属性“应用”

来自分类Dev

@ ngrx /使用Angular 2的存储:无法读取未定义的属性

来自分类Dev

angular2形式-无法读取未定义的属性替换

来自分类Dev

Angular2 + RxJS-无法读取未定义的下一个属性

来自分类Dev

使用回调函数作为Component @Input()时的Angular2未定义对象属性

来自分类Dev

Angular 2属性指令输入值未定义且未正确设置

来自分类Dev

Angular2 beta 11无法读取未定义的属性区域

来自分类Dev

是否有像Angular2模板一样的JavaScript未定义属性处理

来自分类Dev

更新后的Angular 2我收到此错误:无法读取未定义的属性“区域”

来自分类Dev

Angular 2子路由(v3)'无法读取未定义的属性'annotations''

Related 相关文章

  1. 1

    属性未定义的Angular2和TypeScript

  2. 2

    Angular 2-组件属性在方法中未定义

  3. 3

    无法读取未定义Angular 2的属性

  4. 4

    Angular 2 ngFor访问属性时未定义

  5. 5

    Angular - Ionic 2 - 无法读取未定义的属性“订阅”

  6. 6

    (Angular2 和 Typescript)Angular 的 DatePicker 无法读取未定义的属性“切换”

  7. 7

    NgZone / Angular2 / Ionic2 TypeError:无法读取未定义的属性“运行”

  8. 8

    Angular 2 Component全局变量在Reactive Form控制器valueChanges事件中未定义

  9. 9

    Angular2-未定义OnInit

  10. 10

    Angular2'this'未定义

  11. 11

    Angular 2 ContentChild未定义

  12. 12

    参数未定义的 Angular 2 路由

  13. 13

    Angular 2 this.data 未定义

  14. 14

    Angular2-TypeError:无法读取(Typescript)中未定义的属性'Id'

  15. 15

    无法读取Angular 2中的嵌套调用中未定义的属性“ subscribe”

  16. 16

    Angular2 * ngFor:“无法读取未定义的属性'0'”

  17. 17

    Angular 2异常:TypeError:无法读取未定义的属性“ annotations”

  18. 18

    Angular 2 ViewChild不起作用-无法读取未定义的属性nativeElement

  19. 19

    Webpacked Angular2应用程序TypeError:无法读取未定义的属性“ getOptional”

  20. 20

    Angular2 IE11无法获取未定义或空引用的属性“应用”

  21. 21

    @ ngrx /使用Angular 2的存储:无法读取未定义的属性

  22. 22

    angular2形式-无法读取未定义的属性替换

  23. 23

    Angular2 + RxJS-无法读取未定义的下一个属性

  24. 24

    使用回调函数作为Component @Input()时的Angular2未定义对象属性

  25. 25

    Angular 2属性指令输入值未定义且未正确设置

  26. 26

    Angular2 beta 11无法读取未定义的属性区域

  27. 27

    是否有像Angular2模板一样的JavaScript未定义属性处理

  28. 28

    更新后的Angular 2我收到此错误:无法读取未定义的属性“区域”

  29. 29

    Angular 2子路由(v3)'无法读取未定义的属性'annotations''

热门标签

归档