Home > other >  how to use this in a callback-function?
how to use this in a callback-function?

Time:10-14

I use a third-Party-Component for which I have to create an Object for configuration like itemMovementOptions in the following sample code.

export class AppComponent implements OnInit {
    readonly itemMovementOptions = {
      threshold: {
        horizontal: 25,
        vertical: 25,
      },
      events: {
        onMove({ items }) {
          for (let i = 0, len = items.after.length; i < len; i  ) {
            const item = items.after[i];
            if (!this.canMove(item)) return items.before;
          }
          return items.after;
        },
      },
    };

    public canMove(item) {
       // ...
    }

    readonly config = {
        ItemResizing(this.itemResizeOptions),
        ItemMovement(this.itemMovementOptions),
    }

    ngOnInit(): void {
      GSTC.api.stateFromConfig(this.config);
    }
}

My Problem is now, that this is not pointing to AppComponent when the code will be executed so it could not find the method canMove().

Can someone help me, how I can solve this? I have to use canMove on several placed and do not want duplicate the code and putting it into the callback.

CodePudding user response:

this binding is a source of confusion for new JS developers:

  • For regular functions it comes from the call context.
  • Arrow functions capture the this where the function is created rather than where it is invoked.

Observe:

class AppComponent  {
  onMoveFunction() {
    console.log("From onMoveFunction", this);
  }

  onMoveArrow = () => {
    console.log("From onMoveArrow", this);
  }
}

const c = new AppComponent();
const callbackFunction = c.onMoveFunction
const callbackArrow = c.onMoveArrow

c.onMoveFunction() // "From onMoveFunction",  AppComponent: {} 
c.onMoveArrow()    // "From onMoveArrow",  AppComponent: {} 
callbackFunction() // "From onMoveFunction",  undefined 
callbackArrow()    // "From onMoveArrow",  AppComponent: {} 

Another option is to use bind().

For more info:

CodePudding user response:

There are two options here depending on the content of your canMove() function:

  1. If canMove() does not contain any references to this itself, that is, its logic is independent of the class/component that it is in, for example:

    app.component.ts

    canMove(item): boolean {
      return item.canMove;
    }
    

    then we can make the function static and reference it as follows:

    app.component.ts

    static canMove(item): boolean {
      return item.name;
    }
    
    ...
    if (!AppComponent.canMove(item)) return items.before;
    ...
    

    Note: This approach is also valid if the function is not in the component class, e.g.

    utilities.ts

    class Utilities {
      static canMove(item): boolean {
        return item.name;
      }
    }
    

    app.component.ts

    ...
    if (!Utilities.canMove(item)) return items.before;
    ...
    
  2. If canMove() does contain references to this, i.e. its logic is dependent on some content in the class/component that it is in, for example:

    app.component.ts

    canMove(item): boolean {
      return item.canMove && this.canMoveOverride;
    }
    

    we then need to provide the originating class context to the function when it is referenced so that when it is executed, all of the this. variables it needs to access (which are all defined in AppComponent) will be available. This is achieved using .bind() (docs)

    app.component.ts

    ...
    if (!this.canMove(item).bind(this)) return items.before;
    ...
    
  • Related