Reputation: 722
Okay so I have been facing the dreadful:
TypeError: Cannot read property 'Id' of undefined
Before we get started:
@angular/cli: 1.4.4 node: 6.10.3 npm: 3.10.10
Just to give more context, I am trying to perform one way data binding to edit a component by taking the Id from its component class and flow in a single direction to display the view template. That's all.
Below is the following that will hopefully try reproduce the problem and in turn figure out a solution.
CREATE TABLE [ExampleTable]
(
[Id] [int] IDENTITY(1,1) NOT NULL,
[Col2] [nvarchar](50) NULL,
[Col3] [int] NULL,
[Col4] [int] NULL
)
export interface ExampleTable {
Id;
Col2;
Col3;
Col4;
}
export class CreateExampleTableModel {
SomeForeignKey?: number;
Col2: string;
Col2: number;
Col2: number;
}
export class EditExampleTable {
}
import {
Component
} from '@angular/core';
import {
Router
} from "@angular/router";
import {
EmptyTableServiceService
} from "../../services/empty-table.service";
import {
EmptyTable
} from "../../models/outModels/EmptyTable";
@Component({
selector: 'app-empty-tables',
templateUrl: './empty-tables.component.html',
styleUrls: ['./empty-tables.component.css']
})
export class EmptyTablesComponent {
//Table data
emptyTable: EmptyTable[];
constructor(
private router: Router,
private emptyTableServiceService: EmptyTableServiceService) {
}
edit(emptyTable: EmptyTable) {
this.router.navigate(['emptyTables/edit', emptyTable.Id]);
}
}
import {
Injectable
} from '@angular/core';
import {
Http
} from '@angular/http';
import 'rxjs/add/operator/toPromise';
import {
EmptyTable,
CreateExampleTableModel
} from "../models/outModels/EmptyTable";
@Injectable()
export class EmptyTableService {
constructor(private http: Http, ) {}
getEmptyTable(Id: string): Promise<EmptyTable> {
return this.http.get(`${this.auth.apiUrl}/api/emptyTables/get/${Id}`, { headers: this.auth.header })
.toPromise()
.then(response => response.json() as EmptyTable)
.catch(error => this.logging.handleError(error));
}
update(emptyTable: EmptyTable): Promise < EmptyTable > {
return this.http.post(`${this.auth.apiUrl}/api/emptyTables/update`, JSON.stringify(emptyTable), {
headers: this.auth.header
})
.toPromise()
.then(response => response.json() as EmptyTable)
.catch(error => this.logging.handleError(error));
}
}
import {
Component,
OnInit
} from '@angular/core';
import {
ActivatedRoute,
ParamMap,
Router
} from '@angular/router';
import {
EmptyTableService
} from "../../../services/empty-table.service";
import {
EmptyTable
} from "../../../models/outModels/EmptyTable";
export class EmptyTableEditComponent implements OnInit {
model: EmptyTable;
constructor(
private route: ActivatedRoute,
private router: Router,
private emptyTableService: EmptyTableService
) {}
ngOnInit() {
this.loading = true;
this.route.paramMap
.switchMap((params: ParamMap) => this.emptyTableService.getEmptyTable(params.get('Id')))
.subscribe(emptyTable => {
this.model = emptyTable;
});
}
goBack(): void {
this.router.navigate(['/emptyTables']);
}
save(): void {
this.loading = true;
this.emptyTableService.update(this.model).then(
emptyTable => {
this.model = emptyTable;
},
error => {
console.log(error);
}
);
}
}
My suspicion is that in my getEmptyTable(Id: string)
which returns a Promise
of EmptyTables
is that I am passing in my Id parameter as a string value whereas in my table definition from my DB it is an integer
however according to my understanding, url parameters are always in string format. I tried the following:
i. Setting my Id
to a number
data type and I call the toString()
on the Id
parameter in the apiUrl
like so:
getEmptyTable(Id: number): Promise<EmptyTable> {
return this.http.get(`${this.auth.apiUrl}/api/emptyTables/get/${Id.toString()}`, { headers: this.auth.header })
.toPromise()
.then(response => response.json() as EmptyTable)
.catch(error => this.logging.handleError(error));
}
But this does not make much of a difference. Lastly, please find the view template which I render:
<div class="container">
<p-messages [(value)]="messages"></p-messages>
<p-panel *ngIf="model">
<p-header>
Edit EmptyTable {{model.Name}}
</p-header>
<form name="form" (ngSubmit)="save()">
<div class="form-group">
<label>Col 2</label>
<input type="text" class="form-control" name="col2" [(ngModel)]="model.Col2" required />
</div>
<div class="form-group">
<label>Col 3</label>
<input type="text" class="form-control" name="col3" [(ngModel)]="model.Col3" required />
</div>
<div class="form-group">
<button pButton type="button" class="ui-button-secondary" (click)="goBack()" label="Back" icon="fa-chevron-left"></button>
<button pButton class="ui-button-success pull-right" label="Save" icon="fa-save"></button>
<app-loader *ngIf="loading"></app-loader>
</div>
</form>
</p-panel>
</div>
To wrap this up, it complains in the following function:
edit(emptyTable: EmptyTable) {
this.router.navigate(['emptyTables/edit', emptyTable.Id]);
}
Note: Please don't run the snippets as there is no output to them. This was the quickest way to format my code. Manual indentation was not cutting it.
Upvotes: 1
Views: 1807
Reputation: 722
The problem was found below:
<ng-template let-user="rowData" pTemplate="body">
<button type="button" pButton (click)="edit(distributor)" icon="fa-edit"></button>
</ng-template>
let-user
should have been changed to let-distributor
and all works.
Upvotes: 1