Angular2 RC5:无法绑定到“属性X”,因为它不是“子组件”的已知属性

前端之家收集整理的这篇文章主要介绍了Angular2 RC5:无法绑定到“属性X”,因为它不是“子组件”的已知属性前端之家小编觉得挺不错的,现在分享给大家,也给大家做个参考。
我有一个基于Angular2种子项目的小Angular2项目,我正在尝试升级到Angular2 RC5.

我的项目有一些功能,其中一个叫做“家”.家庭组件使用称为create-report-card-form的子组件.我已经在home.module中声明了home和create-report-card-form组件(见下面的代码),并得到这个错误

Unhandled Promise rejection: Template parse errors:
Can't bind to 'currentReportCardCount' since it isn't a known property of 'create-report-card-form'.

1. If 'create-report-card-form' is an Angular component and it has 'currentReportCardCount' input,then verify that it is part of this module.

项目结构

-app
    - app.module.ts
    - app.component.ts
    - +home
        - home.module.ts 
        - home.component.ts
        - home.component.html
        - create-report-card-form.component.ts
        - create-report-card-form.component.html
    - +<other "features">
    - shared
        - shared.module.ts

home.module

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

import { SharedModule } from '../shared/shared.module';
import { DataService } from '../shared/services/index';
import { HomeComponent } from './home.component';
import { CreateReportCardFormComponent } from './create-report-card-form.component';

@NgModule({
    imports: [CommonModule,SharedModule,ReactiveFormsModule],declarations: [HomeComponent,CreateReportCardFormComponent],exports: [HomeComponent,providers: [DataService]
})

export class HomeModule { }

app.module

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { APP_BASE_HREF } from '@angular/common';
import { RouterModule } from '@angular/router';
import { HttpModule } from '@angular/http';
import { AppComponent } from './app.component';
import { routes } from './app.routes';

import { AboutModule } from './+about/about.module';
import { HomeModule } from './+home/home.module';
import {TestModule} from './+test/test.module';
import {VoteDataEntryModule} from './+vote-data-entry/vote-data-entry.module';
import { SharedModule } from './shared/shared.module';

@NgModule({
  imports: [BrowserModule,HttpModule,RouterModule.forRoot(routes),AboutModule,HomeModule,TestModule,VoteDataEntryModule,SharedModule.forRoot()],declarations: [AppComponent],providers: [{
    provide: APP_BASE_HREF,useValue: '<%= APP_BASE %>'
  }],bootstrap: [AppComponent]

})

export class AppModule { }

创建报告卡,form.component.ts

import { Component,Input,Output,EventEmitter,OnInit} from '@angular/core';
import { FormBuilder,FormGroup,FormControl } from '@angular/forms';
// import { Dialog,Dropdown,SelectItem,Header,Footer,Messages,Message } from 'primeng/primeng';
import { SelectItem,Message } from 'primeng/primeng';

import {ReportCard,ReportCardDataSource} from '../shared/index';
import {CREATE_REPORT_CARD_FORM_HEADING,EDIT_REPORT_CARD_FORM_HEADING} from './constants';

@Component({
    moduleId: module.id,selector: 'create-report-card-form',templateUrl: 'create-report-card-form.component.html'
})
export class CreateReportCardFormComponent implements OnInit {

    @Input() public reportCardDataSourcesItems: SelectItem[];
    @Input() public reportCardYearItems: SelectItem[];
    @Input() errorMessages: Message[];

    @Output() reportCardCreated = new EventEmitter<ReportCard>();
    @Output() editReportCardFormValueChanged = new EventEmitter<ReportCard>();

    public editReportCardForm: FormGroup;
    private selectedReportCardDataSourceIdControl: FormControl;
    private selectedReportCardYearControl: FormControl;

    // TODO: remove this hack for resetting the angular 2 form once a real solution is available (supposedly in RC5)
    private isFormActive: boolean = true;
    private formHeaderString: string = CREATE_REPORT_CARD_FORM_HEADING;
    private formDialogVisible: boolean = false;
    private isCreatingNewReportCard = false;  // false implies that we are updating an existing report card

    constructor(private fb: FormBuilder) {
    }

    configureForm(selectedReportCard: ReportCard,createNewReport: boolean) {
        this.isCreatingNewReportCard = createNewReport;

        this.resetForm();

        this.selectedReportCardDataSourceIdControl.updateValue(selectedReportCard.reportCardDataSource.reportCardSourceId);

        this.selectedReportCardYearControl.updateValue(selectedReportCard.reportCardYear);

        if (createNewReport) {
            this.formHeaderString = CREATE_REPORT_CARD_FORM_HEADING;
        } else {
            // updating an existing report card
            this.formHeaderString = EDIT_REPORT_CARD_FORM_HEADING +
                selectedReportCard.reportCardYear + ' ' + selectedReportCard.reportCardDataSource.reportCardSourceName;
        }

        this.editReportCardForm.valueChanges.subscribe(data => this.onFormValueChanged(data));
    }

    customGroupValidator(reportCardDataSourceIdControl: FormControl,reportCardYearControl: FormControl,isCreatingNewReportCard: boolean) {
        return (group: FormGroup): { [key: string]: any } => {

            // missing data error ...
            if (!reportCardDataSourceIdControl.value || !reportCardYearControl.value) {
                return { 'requiredDataError': 'Report card year AND provider must be selected.' };
            }

            // invalid data error ...
            if (isCreatingNewReportCard) {
                if (!reportCardDataSourceIdControl.touched || !reportCardYearControl.touched) {
                    return { 'requiredDataError': 'Report card year AND provider must be selected.' };
                }
            } else {
                if (!reportCardDataSourceIdControl.touched && !reportCardYearControl.touched) {
                    return { 'requiredDataError': 'Report card year OR provider must be selected.' };
                }
            }

            // return null to indicate the form is valid
            return null;
        };
    }

    hideFormDialog() {
        this.formDialogVisible = false;
    }

    showFormDialog() {
        // hide any prevIoUs errors
        this.errorMessages = [];
        this.formDialogVisible = true;
    }

    createForm() {
        // by default,configure the form for new report card creation by setting
        // the initial values of both dropdowns to empty string
        this.selectedReportCardDataSourceIdControl = new FormControl('');
        this.selectedReportCardYearControl = new FormControl('');

        this.editReportCardForm = this.fb.group({
            selectedReportCardDataSourceIdControl: this.selectedReportCardDataSourceIdControl,selectedReportCardYearControl: this.selectedReportCardYearControl
        },{
                validator: this.customGroupValidator(this.selectedReportCardDataSourceIdControl,this.selectedReportCardYearControl,this.isCreatingNewReportCard),asyncValidator: this.duplicateReportCardValidator.bind(this)
            });
    }

    duplicateReportCardValidator() {
        return new Promise(resolve => {

            if ((this.errorMessages) && this.errorMessages.length === 0) {
                resolve({ uniqueReportCard: true });
            } else {
                resolve(null);
            }
        });
    }

    showError(errorMessages: Message[]) {
        this.errorMessages = errorMessages;
    }

    ngOnInit() {
        this.createForm();
    }

    onEditReportCardFormSubmitted() {

        let newReportCard = this.getReportCard(
            this.selectedReportCardDataSourceIdControl.value,this.selectedReportCardYearControl.value,this.reportCardDataSourcesItems
        );

        this.reportCardCreated.emit(newReportCard);
    }

    resetForm() {
        this.createForm();
        this.isFormActive = false;
        setTimeout(() => this.isFormActive = true,0);
    }

    onFormValueChanged(data: any) {
        let newReportCard = this.getReportCard(
            this.selectedReportCardDataSourceIdControl.value,this.reportCardDataSourcesItems
        );

        this.editReportCardFormValueChanged.emit(newReportCard);
    }

    private getReportCard(reportCardDataSourceIdString: string,reportCardYearString: string,reportCardDataSourceItems: SelectItem[]): ReportCard {

        let selectedReportCardYear: number = Number(reportCardYearString);
        let selectedProviderReportCardId: number = Number(reportCardDataSourceIdString);

        let selectedProviderReportCardName: string = 'Unknown Report Card';

        for (var i = 0; i < this.reportCardDataSourcesItems.length; i++) {
            var element = this.reportCardDataSourcesItems[i];
            if (Number(element.value) === selectedProviderReportCardId) {
                selectedProviderReportCardName = element.label;
                break;
            }
        }

        let reportCard: ReportCard = new ReportCard();

        reportCard.reportCardYear = selectedReportCardYear;

        reportCard.reportCardDataSource = new ReportCardDataSource(
            selectedProviderReportCardId,selectedProviderReportCardName
        );

        return reportCard;
    }
}

创建报告卡,form.component.html

<p-dialog header={{formHeaderString}} [(visible)]="formDialogVisible" [responsive]="true" showEffect="fade "
    [modal]="true" width="400">
    <form *ngIf="isFormActive" [formGroup]="editReportCardForm" (ngSubmit)="onEditReportCardFormSubmitted()">
        <div class="ui-grid ui-grid-responsive ui-fluid " *ngIf="reportCardDataSourcesItems ">
            <div class="ui-grid-row ">
                <p-dropdown [options]="reportCardDataSourcesItems" formControlName="selectedReportCardDataSourceIdControl" [autoWidth]="true"></p-dropdown>
            </div>
            <div class="ui-grid-row ">
                <p-dropdown [options]="reportCardYearItems" formControlName="selectedReportCardYearControl" [autoWidth]="true"></p-dropdown>
            </div>
            <div class="ui-grid-row ">
                <p-messages [value]="errorMessages"></p-messages>
            </div>
            <footer>
                <div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix ">
                    <button type="submit" pButton icon="fa-check " 
                    [disabled]="!editReportCardForm?.valid" label="Save "></button>
                </div>
            </footer>
        </div>
    </form>
</p-dialog>

home.component.ts

import { Component,OnInit,ViewChild } from '@angular/core';
// // import { REACTIVE_FORM_DIRECTIVES } from '@angular/forms';
// import {ROUTER_DIRECTIVES} from '@angular/router';
// import { InputText,Panel,Message,Growl,Dialog,DataTable,Column,Tooltip } from 'primeng/primeng';
import { Message,SelectItem } from 'primeng/primeng';

import {CreateReportCardFormComponent} from './create-report-card-form.component';
import { ReportCardDataSource,ReportCard,ProviderData,DataService,DUPLICATE_REPORT_CARD_MESSAGE } from '../shared/index';
import {ReportCardCommands} from './enums';

/**
 * This class represents the lazy loaded HomeComponent.
 */
@Component({
  moduleId: module.id,selector: 'sd-home',templateUrl: 'home.component.html',styleUrls: ['home.component.css']
  //,directives: [CreateReportCardFormComponent]
})

export class HomeComponent implements OnInit {

  public growlMessages: Message[] = [];
  public createReportCardError: Message[] = [];
  public reportCardDataSourcesItems: SelectItem[] = [{ label: 'Select Provider',value: '' }];
  public reportCardYearItems: SelectItem[] = [{ label: 'Select Year',value: '' }];
  public providerData: ProviderData = new ProviderData();
  public displayReportCardDeleteConfirmation: boolean = false;

  private isCreatingNewReportCard: boolean = true;
  private selectedReportCard: ReportCard;

  @ViewChild(CreateReportCardFormComponent)
  private createReportCardFormComponent: CreateReportCardFormComponent;

  constructor(private dataService: DataService) { }

  ngOnInit() {
    let reportCardDataSources: ReportCardDataSource[] = this.dataService.getReportCardDataSources();

    for (var i = 0; i < reportCardDataSources.length; i++) {
      var element = reportCardDataSources[i];
      this.reportCardDataSourcesItems.push({ label: element.reportCardSourceName,value: element.reportCardSourceId });

      // retrieve data from localStorage if available
      this.providerData = this.dataService.getProviderData();
    }

    // initialize report card years
    const minYear: number = 2000;
    // TODO: maxYear should be sourced from the server by a service
    let maxYear: number = (new Date()).getFullYear();

    for (var i = maxYear; i >= minYear; i--) {
      this.reportCardYearItems.push({ value: i.toString(),label: i.toString() });
    }
  }

  // Returns the index of the report card in providerData.reportCards that has the same reporCardSourceId
  // and reportCardYear as selectedReportCard,or -1 if there is no match.
  indexOf(selectedReportCard: ReportCard): number {
    return this.providerData.reportCards.findIndex(x =>
      x.reportCardDataSource.reportCardSourceId === selectedReportCard.reportCardDataSource.reportCardSourceId &&
      x.reportCardYear === selectedReportCard.reportCardYear);
  }

  onReportCardCreated(newReportCard: ReportCard) {
    if (newReportCard) {

      if ((this.indexOf(newReportCard) > -1)) {
        // attemp to create a duplicate report card; show error
        this.setCreateReportCardFromErrorMessage(DUPLICATE_REPORT_CARD_MESSAGE);
      } else {
        if (this.isCreatingNewReportCard) {
          // save new report card
          this.createReportCardError = [];
          this.createReportCardFormComponent.hideFormDialog();
          this.providerData.reportCards.splice(0,newReportCard);

          this.createReportCardFormComponent.hideFormDialog();

        } else {
          // update existing report card
          let reportCardToUpdateIndex: number = this.indexOf(this.selectedReportCard);

          if (reportCardToUpdateIndex > -1) {
            this.providerData.reportCards[reportCardToUpdateIndex].reportCardDataSource.reportCardSourceId
              = newReportCard.reportCardDataSource.reportCardSourceId;
            this.providerData.reportCards[reportCardToUpdateIndex].reportCardDataSource.reportCardSourceName
              = newReportCard.reportCardDataSource.reportCardSourceName;
            this.providerData.reportCards[reportCardToUpdateIndex].reportCardYear
              = newReportCard.reportCardYear;
          }
        }
        this.dataService.storeProviderData(this.providerData);
        this.isCreatingNewReportCard = true;
        this.clearCreateReportCardFormErrorMessage();
        this.createReportCardFormComponent.hideFormDialog();
      }
    }
  }

  editReportCardFormValueChanged(newReportCard: ReportCard) {
    if (this.indexOf(newReportCard) === -1) {
      // clear duplicate report card error message in 'create report card' dialog
      this.clearCreateReportCardFormErrorMessage();
    } else {
      // set duplicate report card error message
      this.setCreateReportCardFromErrorMessage(DUPLICATE_REPORT_CARD_MESSAGE);
    }
  }

  onAddReportCardButtonClicked() {
    this.isCreatingNewReportCard = true;
    this.createReportCardFormComponent.configureForm(new ReportCard(),this.isCreatingNewReportCard);
    this.createReportCardFormComponent.showFormDialog();
  }

  onReportCardDeleteButtonClicked(reportCard: ReportCard) {
    this.reportCardCommandExecute(reportCard,ReportCardCommands.Delete);
  }

  onReportCardEditButtonClicked(reportCard: ReportCard) {
    this.reportCardCommandExecute(reportCard,ReportCardCommands.EditReportCard);
  }

  onAddVotesRouterLinkClicked(reportCard: ReportCard) {
    this.reportCardCommandExecute(reportCard,ReportCardCommands.EditVotes);
  }

  onReportCardDeleteConfirmButtonClick(isDeleteOk: boolean) {
    if (isDeleteOk) {
      this.providerData.reportCards.splice(this.providerData.selectedReportCardIndex,1);
      // store updated reportCards in local storage
      this.dataService.storeProviderData(this.providerData);
    }
    this.displayReportCardDeleteConfirmation = false;
  }

  reportCardCommandExecute(reportCard: ReportCard,command: ReportCardCommands) {
    this.providerData.selectedReportCardIndex = this.indexOf(reportCard);
    this.selectedReportCard = reportCard;

    switch (command) {
      case ReportCardCommands.EditVotes:
        this.dataService.storeProviderData(this.providerData);
        break;
      case ReportCardCommands.Delete:
        this.displayReportCardDeleteConfirmation = true;
        break;
      case ReportCardCommands.EditReportCard:
        this.isCreatingNewReportCard = false;
        this.createReportCardFormComponent.configureForm(reportCard,this.isCreatingNewReportCard);
        this.createReportCardFormComponent.showFormDialog();
        break;
      default:
        break;
    }
  }

  private setCreateReportCardFromErrorMessage(message: Message) {
    this.createReportCardError = [];
    this.createReportCardError.push(message);

    this.createReportCardFormComponent.showError(this.createReportCardError);
  }

  private clearCreateReportCardFormErrorMessage() {
    this.createReportCardError = [];
    this.createReportCardFormComponent.showError(this.createReportCardError);
  }
}

home.component.html

<p-growl [value]="growlMessages" sticky="sticky"></p-growl>
<p-dataTable [value]="providerData.reportCards" [paginator]="true" rows="15" [responsive]="true">
  <header>
    <div>
      <h1>Report Cards ({{providerData.reportCards.length}})</h1>
    </div>
    <button type="button" pButton icon="fa-plus" (click)="onAddReportCardButtonClicked()" label="Add" title="Add new report card"></button>
  </header>
  <p-column styleClass="col-button">
    <template let-reportCard="rowData">
      <button type="button" pButton (click)="onReportCardEditButtonClicked(reportCard)" icon="fa-pencil" title="Edit report card"></button>
    </template>
  </p-column>
  <p-column field="reportCardDataSource.reportCardSourceName" header="Report Card" [sortable]="true"></p-column>
  <p-column field="reportCardYear" header="Year" [sortable]="true"></p-column>
  <p-column header="Votes" [sortable]="false">
    <template let-reportCard="rowData">
      {{reportCard.votes.length}}
      <!--<button type="button" pButton icon="fa-pencil-square" (click)="editVotes(reportCard)" title="Edit votes"></button>-->
      <a [routerLink]="['/votes']" (click)="onAddVotesRouterLinkClicked(reportCard)">Edit</a>
    </template>
  </p-column>
  <p-column styleClass="col-button">
    <template let-reportCard="rowData">
      <button type="button" pButton (click)="onReportCardDeleteButtonClicked(reportCard)" icon="fa-trash" title="Delete report card"></button>
    </template>
  </p-column>
</p-dataTable>

<create-report-card-form [currentReportCardCount]="providerData.reportCards.length" [reportCardDataSourcesItems]="reportCardDataSourcesItems"
  [reportCardYearItems]="reportCardYearItems" (reportCardCreated)=onReportCardCreated($event) (editReportCardFormValueChanged)=editReportCardFormValueChanged($event)>
</create-report-card-form>

<p-dialog header="Confirm Deletion" [(visible)]="displayReportCardDeleteConfirmation" modal="modal" showEffect="fade">
  <p>
    Delete the following report card and all related data (<strong>NO undo</strong>)?
  </p>
  <p>
    <strong>{{providerData?.reportCards[providerData.selectedReportCardIndex]?.reportCardDataSource?.reportCardSourceName}}</strong><br/>
    <strong>{{providerData?.reportCards[providerData.selectedReportCardIndex]?.reportCardYear}}</strong>
  </p>
  <footer>
    <div class="ui-dialog-buttonpane ui-widget-content ui-helper-clearfix">
      <button type="button" pButton icon="fa-close" (click)="onReportCardDeleteConfirmButtonClick(false)" label="No"></button>
      <button type="button" pButton icon="fa-check" (click)="onReportCardDeleteConfirmButtonClick(true)" label="Yes"></button>
    </div>
  </footer>
</p-dialog>
<create-report-card-form [currentReportCardCount]="providerData.reportCards.length" ...
                         ^^^^^^^^^^^^^^^^^^^^^^^^

在您的HomeComponent模板中,您尝试绑定到CreateReportCardForm组件上不存在的输入.

在CreateReportCardForm中,这些是您唯一的三个输入:

@Input() public reportCardDataSourcesItems: SelectItem[];
@Input() public reportCardYearItems: SelectItem[];
@Input() errorMessages: Message[];

为currentReportCardCount添加一个,你应该很好去.

猜你在找的Angularjs相关文章