i trying create custom filter filter array of objects object's title attribute, , display objects title contains search substring. problem is, undefined
gets passed pipe component.
the pipe used in template in *ngfor loop. template code looks this:
<div class="col-md-2" *ngfor="let strategy of (strategies | namefilter: searchstrategytext)">
in context, strategies
array of strategy objects, searchstrategytext
string two-way data binding input field.
the custom pipe code follows:
import {injectable, pipe, pipetransform} '@angular/core'; import {strategy} './strategy'; @pipe({ name: 'namefilter' }) @injectable() export class namefilter implements pipetransform { transform(strategies: strategy[], searchstring: string): strategy[] { return strategies.filter(strategy => strategy.title.indexof(searchstring) !== -1); } }
the versions of angular using follows:
angular-cli: 1.0.0-beta.28.3 node: 6.9.2 os: darwin x64 @angular/common: 4.0.0 @angular/compiler: 4.0.0 @angular/core: 4.0.0 @angular/forms: 4.0.0 @angular/http: 4.0.0 @angular/platform-browser: 4.0.0 @angular/platform-browser-dynamic: 4.0.0 @angular/router: 4.0.0
i have scoured internet , tried variety of approaches, approach seemed closest angular describes here: https://angular.io/docs/ts/latest/guide/pipes.html
what missing here? if left out important info, let me know.
edit: html input section two-way data binding searchstrategytext:
<div class="form-group has-feedback has-feedback-left"> <input class="form-control" [(ngmodel)]="searchstrategytext" name="searchstrategytext" (focus)="selectallcontent($event)" type="text" placeholder="strategy search"> <i class="glyphicon glyphicon-search form-control-feedback"></i> </div>
i make custom pipe globally available via appmodule importing , adding declarations array.
edit #2: getting strategies
array strategyservice
have mocked getstrategies()
function returns mock data class.
code component gets strategies service:
getstrategies(): void { this.strategyservice.getstrategies().then(strategies => this.strategies = strategies); }
strategyservice component:
import { injectable } '@angular/core'; import { strategy } './strategy'; import { strategies } './mock-strategies'; import { active_strategies } './mock-active-strategies'; @injectable() export class strategyservice { getstrategies(): promise<strategy[]> { return promise.resolve(strategies); } getactivestrategies(): promise<strategy[]>{ return promise.resolve(active_strategies); } }
mock data component:
import { strategy } './strategy'; export const strategies: strategy[] = [ {title: "key reverse long entry", description: "lorem ipsum dolor sit amet, consectetur adipiscing elit.", type: "strategy template", modifiedtime: 1461155000, symbollist:"s&p 100", deploystatus:"load", action:"buy", isactive: false}, {title:"key reverse short entry", description:"lorem ipsum dolor sit amet, consectetur adipiscing elit.", type:"strategy template", modifiedtime: 1461154940, symbollist:"s&p 100", deploystatus:"unload", action:"buy", isactive: false} ];
there's lot more mock data, shortened brevity.
edit #3: strategylist component controlling of this:
import { component, oninit, viewchild } '@angular/core'; import { tabsetcomponent } 'ng2-bootstrap'; import { strategy } './strategy'; import { strategyservice } './strategy.service'; @component({ selector: 'strategy-list', templateurl: './strategy-list.component.html', styleurls: ['./strategy-list.component.css'] }) export class strategylistcomponent implements oninit { @viewchild('statictabs') statictabs: tabsetcomponent; strategies: strategy[]; activestrategies: strategy[] = []; totalitems = 0; // previous html: (allsignals | filter:searchsignaltext).length filterselected = false; searchstrategytext: string; constructor(private strategyservice: strategyservice) { } ngoninit() { this.getstrategies(); this.searchstrategytext = "initial"; } selecttab(tab_id: number){ this.statictabs.tabs[tab_id].active = true; } getstrategies(): void { this.strategyservice.getstrategies().then(strategies => this.strategies = strategies); } getactivestrategies(): void { this.strategyservice.getactivestrategies().then(activestrategies => this.activestrategies = activestrategies); } exists(strategy: strategy): boolean { let idx = this.activestrategies.indexof(strategy); if ( idx > -1){ console.log('strategy active'); return true; } else { console.log('strategy inactive'); return false; } } toggle(strategy: strategy): void { let idx = this.activestrategies.indexof(strategy); if (idx > -1){ console.log("strategy exists in activestrategies"); this.activestrategies.splice(idx, 1); // this.strategyservice.cancelstrategy(strategy); } else { console.log("strategy not exist in activestrategies"); this.activestrategies.push(strategy); // this.strategyservice.activatestrategy(strategy); } } togglefilter(): void{ this.filterselected = !this.filterselected; } }
edit #4: error output:
strategy-list.component.html:9 error context debugcontext_ {view: object, nodeindex: 3, nodedef: object, eldef: object, elview: object} view_strategylistcomponent_2 @ strategy-list.component.html:9 debugcontext_.logerror @ services.ts:571 errorhandler.handleerror @ error_handler.ts:69 (anonymous) @ application_ref.ts:286 zonedelegate.invoke @ zone.js:365 oninvoke @ ng_zone.ts:261 zonedelegate.invoke @ zone.js:364 zone.run @ zone.js:125 (anonymous) @ zone.js:760 zonedelegate.invoketask @ zone.js:398 oninvoketask @ ng_zone.ts:253 zonedelegate.invoketask @ zone.js:397 zone.runtask @ zone.js:165 drainmicrotaskqueue @ zone.js:593 zonetask.invoke @ zone.js:464 zone.js:569 unhandled promise rejection: cannot read property 'filter' of undefined ; zone: <root> ; task: promise.then ; value: typeerror: cannot read property 'filter' of undefined @ namefilter.transform (name-filter.pipe.ts:11) @ object.eval [as updatedirectives] (strategy-list.component.html:9) @ object.debugupdatedirectives [as updatedirectives] (services.ts:273) @ checkandupdateview (view.ts:345) @ callviewaction (view.ts:700) @ execembeddedviewsaction (view.ts:670) @ checkandupdateview (view.ts:389) @ callviewaction (view.ts:700) @ execcomponentviewsaction (view.ts:644) @ checkandupdateview (view.ts:392) @ callviewaction (view.ts:700) @ execcomponentviewsaction (view.ts:644) @ checkandupdateview (view.ts:392) @ callwithdebugcontext (services.ts:645) @ object.debugcheckandupdateview [as checkandupdateview] (services.ts:215) typeerror: cannot read property 'filter' of undefined @ namefilter.transform (http://localhost:3000/app/name-filter.pipe.js:13:26) @ object.eval [as updatedirectives] (ng:///appmodule/strategylistcomponent.ngfactory.js:89:66) @ object.debugupdatedirectives [as updatedirectives] (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:12620:21) @ checkandupdateview (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:12032:14) @ callviewaction (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:12347:17) @ execembeddedviewsaction (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:12319:17) @ checkandupdateview (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:12033:5) @ callviewaction (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:12347:17) @ execcomponentviewsaction (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:12293:13) @ checkandupdateview (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:12038:5) @ callviewaction (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:12347:17) @ execcomponentviewsaction (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:12293:13) @ checkandupdateview (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:12038:5) @ callwithdebugcontext (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:13020:42) @ object.debugcheckandupdateview [as checkandupdateview] (http://localhost:3000/node_modules/@angular/core/bundles/core.umd.js:12560:12) consoleerror @ zone.js:569 handleunhandledrejection @ zone.js:574 _loop_1 @ zone.js:609 drainmicrotaskqueue @ zone.js:613 zonetask.invoke @ zone.js:464 zone.js:571 error: uncaught (in promise): typeerror: cannot read property 'filter' of undefined typeerror: cannot read property 'filter' of undefined @ namefilter.transform (name-filter.pipe.ts:11) @ object.eval [as updatedirectives] (strategy-list.component.html:9) @ object.debugupdatedirectives [as updatedirectives] (services.ts:273) @ checkandupdateview (view.ts:345) @ callviewaction (view.ts:700) @ execembeddedviewsaction (view.ts:670) @ checkandupdateview (view.ts:389) @ callviewaction (view.ts:700) @ execcomponentviewsaction (view.ts:644) @ checkandupdateview (view.ts:392) @ callviewaction (view.ts:700) @ execcomponentviewsaction (view.ts:644) @ checkandupdateview (view.ts:392) @ callwithdebugcontext (services.ts:645) @ object.debugcheckandupdateview [as checkandupdateview] (services.ts:215) @ namefilter.transform (name-filter.pipe.ts:11) @ object.eval [as updatedirectives] (strategy-list.component.html:9) @ object.debugupdatedirectives [as updatedirectives] (services.ts:273) @ checkandupdateview (view.ts:345) @ callviewaction (view.ts:700) @ execembeddedviewsaction (view.ts:670) @ checkandupdateview (view.ts:389) @ callviewaction (view.ts:700) @ execcomponentviewsaction (view.ts:644) @ checkandupdateview (view.ts:392) @ callviewaction (view.ts:700) @ execcomponentviewsaction (view.ts:644) @ checkandupdateview (view.ts:392) @ callwithdebugcontext (services.ts:645) @ object.debugcheckandupdateview [as checkandupdateview] (services.ts:215) @ resolvepromise (zone.js:712) [<root>] @ :3000/node_modules/zone.js/dist/zone.js:638:17 [<root>] @ :3000/node_modules/zone.js/dist/zone.js:654:33 [<root>] @ zone.run (zone.js:125) [<root> => <root>] @ :3000/node_modules/zone.js/dist/zone.js:760:57 [<root>] @ zone.runtask (zone.js:165) [<root> => <root>] @ drainmicrotaskqueue (zone.js:593) [<root>] @ xmlhttprequest.zonetask.invoke (zone.js:464) [<root>]
you need add check if if strategies exist or not clled method inside filter because first time filter called strategies undefined or initialize strategies empty error in component
transform(strategies: strategy[], searchstring: string): strategy[] { if(strategies){ return strategies.filter(strategy => strategy.title.indexof(searchstring) !== -1);} }
rest of code
export class appcomponent implements oninit { title = 'app works!'; strategies = []; constructor(private strategyservice: strategyservice) { } ngoninit() { this.getstrategies(); } getstrategies(): void { this.strategyservice.getstrategies().then((strategies) => this.strategies = strategies); } }
in service
@injectable() export class strategyservice { getstrategies() { return promise.resolve(strategies); } } export const strategies = [ { title: "key reverse long entry", description: "lorem ipsum dolor sit amet, consectetur adipiscing elit.", type: "strategy template", modifiedtime: 1461155000, symbollist: "s&p 100", deploystatus: "load", action: "buy", isactive: false }, { title: "key reverse short entry", description: "lorem ipsum dolor sit amet, consectetur adipiscing elit.", type: "strategy template", modifiedtime: 1461154940, symbollist: "s&p 100", deploystatus: "unload", action: "buy", isactive: false } ];
and filter
@pipe({ name: 'namefilter' }) export class namefilter implements pipetransform { transform(strategies: string[], searchstring: string): string[] { if(strategies) //make sure run check otherwise strategies undefined first time{ return strategies;} } }
first filter gets called empty array , final results https://ibb.co/mzarva https://ibb.co/
Comments
Post a Comment