Search code examples
javascriptangulartypescriptecmascript-6class-fields

How to set an arrow-style function as a default parameter for Input()


So I have a component that displays rows of data in a table. I have an input for the function that should run if someone double clicks a row. I want to default that to doing something with the router.

This works fine:

@Input() rowDoubleClickedFunction: (result: T) => void = this.routeToDetailsPage;
private routeToDetailsPage(result: T) {
    this.router.navigate(['route here']);
}

This is abbreviated to get the point across. I'm really doing some other things in the function before making the router call. But as soon as I change the bottom function to the arrow syntax:

@Input() rowDoubleClickedFunction: (result: T) => void = this.routeToDetailsPage;
private routeToDetailsPage = (result: T) => {
    //Something more complicated with "this" which necessitates using arrow syntax        
    this.router.navigate(['route composed from code above']);
};

I get an error: Property 'routeToDetailsPage' is used before its initialization.ts(2729)

It doesn't appear to be an issue with the linter. Is there a way to do this or am I out of luck?


Solution

  • Class fields are evaluated in order. You're doing

    @Input()
    public rowDoubleClickedFunction = this.routeToDetailsPage;
    private routeToDetailsPage = …;
    

    which accesses the routeToDetailsPage property before it is initialised. Flip them around:

    private routeToDetailsPage = (result: T) => {
        …
    };
    @Input()
    rowDoubleClickedFunction: (result: T) => void = this.routeToDetailsPage;
    

    or if you're not using routeToDetailsPage anywhere else, just drop it entirely and write only

    @Input()
    rowDoubleClickedFunction: (result: T) => void = (result: T) => {
        …
    };