角度 - 组件绑定问题

时间:2017-12-09 07:46:00

标签: angular typescript angular4-forms

我有一个组件绑定问题。我很确定我有语法问题,但我不确定我做错了什么。

完整的源代码位于 feature / 6_ExtendedInputBug 分支(https://github.com/TheMagnificent11/LunchVoting)的https://github.com/TheMagnificent11/LunchVoting/tree/feature/6_ExtendedInputBug处。 develop 分支具有不使用扩展输入组件的工作代码。

输入error.component.ts

这是显示表单字段错误的组件。

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

@Component({
    selector: 'input-error',
    template: './input-error.component.html'
})
export class InputErrorComponent {

    @Input()
    errorMessage: string;

    @Input()
    isError: boolean = true;

}

输入error.component.html

<span class="text-danger" *ngIf="isError">
    {{errorMessage}}
</span>

延伸型input.component.ts

此组件将单个表单字段的标签,输入和验证错误(子组件input-error的集合)组合在一起。

import {
    Component,
    Input,
    ContentChildren,
    QueryList
} from '@angular/core';

import { InputErrorComponent } from '../input-error/input-error.component';

@Component({
    selector: 'extended-input',
    template: './extended-input.component.html'
})
export class ExtendedInputComponent {

    @Input()
    inputName: string = '';

    @Input()
    labelText: string = '';

    @Input()
    isError: boolean = false;

    @ContentChildren(InputErrorComponent)
    errors: QueryList<InputErrorComponent>;

}

延伸型input.component.html

<div class="form-group" [ngClass]="{'has-error':border border-danger}">
    <label for="{{inputName}}">{{labelText}}</label>
    <ng-content select="input-control"></ng-content>
    <div *ngIf="isError">
        <ng-content select="input-errors"></ng-content>
    </div>
</div>

controls.module.ts

具有extended-input组件

的模块
import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ReactiveFormsModule } from '@angular/forms';

import { ExtendedInputComponent } from './extended-input.component.ts';
import { InputErrorComponent } from './input-error.component.ts';

let components = [
    ExtendedInputComponent,
    InputErrorComponent
];

@NgModule({
    declarations: components,
    imports: [
        CommonModule,
        ReactiveFormsModule
    ]
})
export class ControlsModule {
}

register.component.ts

这是使用其他extended-input组件的表单组件。

import { Component } from '@angular/core';
import {
    FormBuilder,
    FormGroup,
    FormControl,
    Validators
} from '@angular/forms';

@Component({
    selector: 'register',
    templateUrl: './register.component.html'
})
export class RegisterComponent {

    registrationForm: FormGroup;

    givenName: FormControl;

    surname: FormControl;

    constructor(private formBuilder: FormBuilder) {
        this.givenName = new FormControl('', [Validators.required, Validators.maxLength(100)]);
        this.surname = new FormControl('', [Validators.required, Validators.maxLength(100)]);

        this.registrationForm = this.formBuilder.group({
            givenName: this.givenName,
            surname: this.surname,
        });
    }

}

register.component.html

<form [formGroup]="registrationForm" (submit)="onSubmit()">

    <extended-input [inputName]="'givenName'" 
                    [labelText]="'Given Name'"
                    [isError]="givenName.touched && givenName.invalid">
        <input-control>
            <input type="text" formControlName="givenName" />
        </input-control>
        <input-errors>
            <input-error [isError]="givenName.hasError('required')">
                Given Name is required
            </input-error>
        </input-errors>
    </extended-input>

    <!-- The above components should produce HTML similar to this -->
    <div class="form-group">
        <label for="surname">Surname</label>
        <input type="text" formControlName="surname" />
        <div [hidden]="surname.valid || surname.untouched">
            <span class="text-danger" [hidden]="!surname.hasError('required')">
                Surname is required
            </span>
        </div>
    </div>

    <button type="submit" [disabled]="!registrationForm.valid">
        Register
    </button>

</form>

条目模块

包含register组件的模块。

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ReactiveFormsModule } from '@angular/forms';

import { ControlsModule } from '../controls/controls.module';

import { RegisterComponent } from './register-component';

@NgModule({
    declarations: components,
    imports: [
        CommonModule,
        ReactiveFormsModule,
        ControlsModule
    ]
})
export class EntryModule {
}

错误

Uncaught Error: Template parse errors:
Can't bind to 'inputName' since it isn't a known property of 'extended-input'.
1. If 'extended-input' is an Angular component and it has 'inputName' input, then verify that it is part of this module.
2. If 'extended-input' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("
        <form [formGroup]="registrationForm" (submit)="onSubmit()">

            <extended-input [ERROR ->][inputName]="'givenName'" 
                            [labelText]="'Given Name'"
                 "): ng:///EntryModule/RegisterComponent.html@9:28
Can't bind to 'labelText' since it isn't a known property of 'extended-input'.
1. If 'extended-input' is an Angular component and it has 'labelText' input, then verify that it is part of this module.
2. If 'extended-input' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("

            <extended-input [inputName]="'givenName'" 
                            [ERROR ->][labelText]="'Given Name'"
                            [isError]="givenName.touched && givenName.inv"): ng:///EntryModule/RegisterComponent.html@10:28
Can't bind to 'isError' since it isn't a known property of 'extended-input'.
1. If 'extended-input' is an Angular component and it has 'isError' input, then verify that it is part of this module.
2. If 'extended-input' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. (""'givenName'" 
                            [labelText]="'Given Name'"
                            [ERROR ->][isError]="givenName.touched && givenName.invalid">
                <input-control>
               "): ng:///EntryModule/RegisterComponent.html@11:28
'input-control' is not a known element:
1. If 'input-control' is an Angular component, then verify that it is part of this module.
2. If 'input-control' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. (""
                            [isError]="givenName.touched && givenName.invalid">
                [ERROR ->]<input-control>
                    <input type="text" formControlName="givenName" />
             "): ng:///EntryModule/RegisterComponent.html@12:16
Can't bind to 'isError' since it isn't a known property of 'input-error'.
1. If 'input-error' is an Angular component and it has 'isError' input, then verify that it is part of this module.
2. If 'input-error' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message.
3. To allow any property add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("
                </input-control>
                <input-errors>
                    <input-error [ERROR ->][isError]="givenName.hasError('required')">
                        Given Name is required
        "): ng:///EntryModule/RegisterComponent.html@16:33
'input-error' is not a known element:
1. If 'input-error' is an Angular component, then verify that it is part of this module.
2. If 'input-error' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. ("
                </input-control>
                <input-errors>
                    [ERROR ->]<input-error [isError]="givenName.hasError('required')">
                        Given Name is requi"): ng:///EntryModule/RegisterComponent.html@16:20
'input-errors' is not a known element:
1. If 'input-errors' is an Angular component, then verify that it is part of this module.
2. If 'input-errors' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. ("input type="text" formControlName="givenName" />
                </input-control>
                [ERROR ->]<input-errors>
                    <input-error [isError]="givenName.hasError('required')">
       "): ng:///EntryModule/RegisterComponent.html@15:16
'extended-input' is not a known element:
1. If 'extended-input' is an Angular component, then verify that it is part of this module.
2. If 'extended-input' is a Web Component then add 'CUSTOM_ELEMENTS_SCHEMA' to the '@NgModule.schemas' of this component to suppress this message. ("
        <form [formGroup]="registrationForm" (submit)="onSubmit()">

            [ERROR ->]<extended-input [inputName]="'givenName'" 
                            [labelText]="'Given Name'"
 "): ng:///EntryModule/RegisterComponent.html@9:12
    at syntaxError (vendor.js:sourcemap:38524)
    at TemplateParser.parse (vendor.js:sourcemap:49621)
    at JitCompiler._compileTemplate (vendor.js:sourcemap:63824)
    at vendor.js:sourcemap:63743
    at Set.forEach (<anonymous>)
    at JitCompiler._compileComponents (vendor.js:sourcemap:63743)
    at vendor.js:sourcemap:63630
    at Object.then (vendor.js:sourcemap:38513)
    at JitCompiler._compileModuleAndComponents (vendor.js:sourcemap:63629)
    at JitCompiler.compileModuleAsync (vendor.js:sourcemap:63558)

有谁知道我做错了什么?

2 个答案:

答案 0 :(得分:1)

如果您在其他模块(extendedInputComponent)中宣布InputErrorComponentControlsModule,则宣布RegisterComponentEntryModule)和ControlsModule }仅在EntryModule中导入,您必须导出您在同一ControlsModule中声明的组件。

即,您的ControlsModule应该像

import { NgModule } from '@angular/core';
import { CommonModule } from '@angular/common';
import { ReactiveFormsModule } from '@angular/forms';

import { ExtendedInputComponent } from './extended-input.component.ts';
import { InputErrorComponent } from './input-error.component.ts';

let components = [
    ExtendedInputComponent,
    InputErrorComponent
];

@NgModule({
    declarations: components,
    imports: [
        CommonModule,
        ReactiveFormsModule
    ],
    exports: components
})
export class ControlsModule {
}

答案 1 :(得分:0)

1. If 'extended-input' is an Angular component and it has 'inputName' input, then verify that it is part of this module.

确保您的组件正确导入。我注意到RegisterComponent在类名末尾有'Component'后缀,但其他的后缀InputError和ExtendedInput没有。你用CLI创建了一个而不是其他的吗?如果您不使用CLI,可能忘了手动将它们导入模块。

之后,我看到了属性绑定的问题。它期望一个表达式在引号内,所以如果你想传入文字文本,你需要在引号内引用。有点奇怪。 [labelText]="Given Name"将查找变量Given和Name,因此需要[labelText]="'Given Name'"。这就是上面的错误:

[ERROR ->][labelText]="Given Name"

你的应用似乎还有其他一些组件input-controlinput-errors,但是我没有在这里看到这些代码,所以无法让一切正常,但这是一个开始。我不能完全遵循ng-content / transclusion的策略,但角度的那部分不是我的强项。