Fix Angular 2 Pipes: Resolve TypeError
Ive been trying to build simple filtering in application -> Show-ur-bugs (https://github.com/fedojo/show-ur-bugs).
Let me introduce the error environment firstly:
project-list.component.ts
import 'rxjs/add/operator/map';
import {Component, OnInit} from '@angular/core';
import {ProjectService} from "../../shared";
import {ProjectListSingleComponent} from "./project/project-list-single.component";
import {FilterData} from "../../filter-data.pipe";
@Component({
moduleId: module.id,
bindings: [ProjectService],
selector: 'app-project-list',
templateUrl: 'project-list.component.html',
styleUrls: ['project-list.component.css'],
directives: [ProjectListSingleComponent],
pipes: [FilterData]
})
export class ProjectListComponent implements OnInit {
projects;
constructor(public projectService:ProjectService) {
}
getProjects() {
this.projectService.getProjects()
.subscribe(
data => {
this.projects = data;
},
error => console.error('Error: ' + error[0]),
() => {}
)
}
ngOnInit() {
this.getProjects();
}
}
project-list.component.html
<input type="text" #filter (keyup)="0">
<project-list-single *ngFor="let project of (projects | filterData: filter.value)"
[project]="project"
class="project"></project-list-single>
filter-data.pipe.ts – ver 1
import {Pipe, PipeTransform} from '@angular/core';
import {ProjectItem} from './projects/index';
@Pipe({
name: 'filterData'
})
export class FilterData implements PipeTransform {
transform(value:ProjectItem[], args:string[]):any {
if (value.length === 0) {
return value;
}
var resultArray = [];
for (let item of value) {
if (item.name.match('^.*' + args[0] + '.*$')) {
resultArray.push(item);
}
}
return resultArray;
}
}
The error occured:
ORIGINAL EXCEPTION: TypeError: Cannot read property ‘length’ of undefined
But which element hasn’t got length? After quick investigation in code it was object which was passed to the Pipe. It hasn’t exist in moment when the Pipe was invoked. So here came an idea to resolve it:
filter-data.pipe.ts – ver 2
import {Pipe, PipeTransform} from '@angular/core';
import {ProjectItem} from './projects/index';
@Pipe({
name: 'filterData'
})
export class FilterData implements PipeTransform {
transform(value:ProjectItem[], args:string[]):any {
if (typeof value === 'object') {
var resultArray = [];
if (args.length === 0) {
for (let item of value) {
resultArray.push(item);
}
}
else {
for (let item of value) {
if (item.name.match('^.*' + args[0] + '.*$')) {
resultArray.push(item);
}
}
}
return resultArray;
}
}
}
Why do you need this condition in pipe?
if (args.length === 0) {
for (let item of value) {
resultArray.push(item);
}
}
When your array of objects will be loaded it will be automatically pushed to Pipe which checks the value from your input. When input is empty the result of the Pipe will be empty too so you wont see your objects in list.
Thanks a lot, I love it this article, it save my life. I been looking for something like this, I break my head about length property and the error, and you explain marvalous.
THANKS. sorry for my english 😉