Ich habe ein kleines Angular2-Projekt, das auf dem Angular2 Seed-Projekt basiert und das ich auf Angular2 RC5 aktualisieren möchte.
Mein Projekt hat einige Funktionen, von denen eine aufgerufen wird home
. Die Home-Komponente verwendet eine untergeordnete Komponente namens create-report-card-form
. Ich habe sowohl das Home als auch die create-report-card-form
Komponenten im home.module
(siehe Code unten) deklariert und erhalte folgende Fehlermeldung :
Nicht behandelte Ablehnung von Versprechungen: Fehler beim Analysieren von Vorlagen: Kann nicht an 'currentReportCardCount' gebunden werden, da dies keine bekannte Eigenschaft von 'create-report-card-form' ist.
- Wenn 'create-report-card-form' eine Angular-Komponente ist und die Eingabe 'currentReportCardCount' hat, überprüfen Sie, ob es Teil dieses Moduls ist.
Projektstruktur
-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, CreateReportCardFormComponent],
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 { }
create-report-card-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.selectedReportCardYearControl.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;
}
}
create-report-card-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, SelectItem, Message, Growl, Dialog, DataTable, Column, Header, Footer, 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, 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>
quelle
Antworten:
In Ihrer HomeComponent-Vorlage versuchen Sie, eine Bindung zu einer Eingabe in der CreateReportCardForm-Komponente herzustellen, die nicht vorhanden ist.
In CreateReportCardForm sind dies Ihre einzigen drei Eingaben:
Fügen Sie eine für currentReportCardCount hinzu, und Sie sollten bereit sein.
quelle
Ich habe es durch Hinzufügen des Präfixes (attr.) Korrigiert:
Leider ist dies noch nicht richtig dokumentiert.
mehr Details hier
quelle
Es gibt mehrere mögliche Ursachen für diesen Fehler:
1) Wenn Sie die Eigenschaft 'x' in Klammern setzen, versuchen Sie, sie zu binden. Überprüfen Sie daher zunächst, ob die Eigenschaft 'x' in Ihrer Komponente mit einem definiert ist
Input()
Dekorateur definiert istIhre HTML-Datei:
Ihre Klassendatei:
(Stellen Sie sicher, dass Sie auch die Klammern haben)
2) Stellen Sie sicher, dass Sie Ihre Komponenten- / Direktiven- / Pipe-Klassen in NgModule registriert haben:
Siehe https://angular.io/guide/ngmodule#declare-directivesWeitere Informationen zum Deklarieren von Anweisungen finden .
3) Kommt auch vor, wenn Sie einen Tippfehler in Ihrer Winkelanweisung haben. Beispielsweise:
Anstatt:
Dies geschieht, weil unter der Haube Angular die Sternsyntax in Folgendes konvertiert:
quelle
<tr my-component></tr>
aber in der@Component
tun Sie diesselector: 'my-component'
anstelle vonselector: '[my-component]'
...Wenn Sie die Angular-CLI zum Erstellen Ihrer Komponenten verwenden, sagen wir
CarComponent
wird sie beispielsweise anapp
den Selektornamen (dhapp-car
) angehängt. Dies löst den obigen Fehler aus, wenn Sie auf die Komponente in der übergeordneten Ansicht verweisen. Daher müssen Sie entweder den Selektornamen in der übergeordneten Ansicht<app-car></app-car>
ändern , um es zu sagen, oder den Selektor in derCarComponent
to ändernselector: 'car'
quelle
Ich bin auf den gleichen Fehler gestoßen, als ich nur vergessen habe, meine benutzerdefinierte Komponente in meinem zu deklarieren.
NgModule
Überprüfen Sie dort, ob die anderen Lösungen für Sie nicht funktionieren.quelle