junk
junk

Reputation: 987

How to use custom decorator in angular injectable service

i wan to use 'AOP' in my angular2 service ,for example,i want to request my server and get data,and i will check it return code ,i will show message by this return code,

for example : here is my service:

@Injectable()
export class TemplatesService {

constructor(private http: HttpHelper) {

}

@show_message
public templates(search_params = {}): Observable<Array<Template>> {
    let params = new URLSearchParams()
    for (let key in search_params) {
        params.set(key, search_params[key])
    }
    return this.http.AUTH_HTTP_GET('api/templates.json?per=10000', params).map(data=> this.http.extractData(data).templates)
}
}

HttpHelper is my angular 2 http wrapper for some custom http header,body etc..

the show_message decorator:

export function  show_message(target:any,key:any,descriptor:any){
    console.log(target,key ,descriptor)
    const method = descriptor.value

    descriptor.value = (...args:any[]) => {

        let ret = method.apply(target, args);

        return ret;
    }

    console.log(method)

    return descriptor;
}

and here is the error:

    VM40526 TemplateIndexComponent_Host.ngfactory.js:5
 ERROR TypeError: Cannot read property 'AUTH_HTTP_GET' of undefined
        at Object.TemplatesService.templates (eval at <anonymous> (app.cfb7cea….js:194), <anonymous>:31:25)
        at TemplatesService.descriptor.value [as templates] (eval at <anonymous> (app.cfb7cea….js:2349), <

Upvotes: 2

Views: 1339

Answers (1)

yurzui
yurzui

Reputation: 214037

You're passing wrong context.

According to the documentation

The expression for the method decorator will be called as a function at runtime, with the following three arguments:

1) Either the constructor function of the class for a static member, or the prototype of the class for an instance member.

2) ..

So target is TemplatesService.prototype in your case but you should call method with current instance.

Try the following

descriptor.value = function(...args:any[]) { // don't forget function 
  let ret = method.apply(this, args); // pass current context

Upvotes: 3

Related Questions