Preserve the scope when calling a method passed as input

Viewed 25

I have a question. It is more of a good practice and share of thoughts than a solution I guess.

So the title I think is quite descriptive but let me show the sample code and explain it deeply.

We have a parent component where we check if provided param id is same with currentId.

parent.component.ts

function isSame(id: number): boolean {
  return id === this.currentId;
}

Pass above func as a input param to a child.

parent.component.html

<child [isSame]="isSame"></child>

Child takes it as an input and call this function.

child.component.ts

@Input() isSame: (id: number) => boolean;

onSave(id): void {
  if(this.isSame(id)){
    return;
  }
  this.save();//whatever
}

The presented above example will not work as expected, because the use of this keyword in parent.component.ts refers to current scope which is child componet (as the result this.currentId is undefined, there is no such a property in scope of child) - which is expected and understandable behavior.

My question is how to overcome this? Maybe the whole concept is wrong? The thing I came up with is to use arrow function in parent component, because of it's feature to preserve scope.

parent.component.ts

isSame = (id: number): boolean => {
  return id === this.currentId;
}

What are your thoughts? Is this a correct way?

Thanks for all insights!

1 Answers

You need to use the bind of javascript to tell it in what scope it should execute on. Please find below the change.

parent.component.ts

function isSame(id: number): boolean {
  return id === this.currentId;
}

Pass above func as a input param to a child.

parent.component.html

<child [isSame]="isSame.bind(this)"></child>

Now after this change, we will be able to execute with the parent scope because we have explicitely informed JS compiler, that its to be executed in the parent context!

Related