Extending Handsontable with custom logic

Tags: #<Tag:0x00007efc729957f8> #<Tag:0x00007efc729955c8>

Hi

I was thinking I should encapsulate my custom HoT related features, like adding a find/replace function, in my own class to be able to test it easier.

It is not as straight forward as I hoped, just extending the Handsontable class.

Since I use it with the “new” keyword I assumed it is a class, and shouldn’t it be possible to just extend it then?

Maybe I’m being naive :stuck_out_tongue:

https://jsfiddle.net/nL1j4wh3/3/

Hi @mottosson

That’s an interesting approach, however, more likely not possible as we allow only editors classes to be expendable, and I think doing it the way you tried it actually extends the base editor as if we define, for example, init() method it will work, at least partially. It creates a new instance of Handsontable, but it’s broken.

The behavior is strange, as some of the base editor methods work, and other are throwing the error. Here’s my example with the init() method: https://jsfiddle.net/handsoncode/uc82Lmtg/

Thanks.

I’m trying another approach where I just keep an instance of HoT in my HotExtended class and manually re-expose the HoT functions used in my application.

Not super elegant. But maybe good enough for now…

Not quite done experimenting yet, so we’ll see if it is a futile endeavor or not in the end :slight_smile:

@mottosson

Sure, please keep us updated, as I’m curious how it will go :slight_smile:

1 Like

So this is how I did.
Not exactly extending Handsontable, but pretty much the same end result.

export class BaseTable {
  public _hot: Handsontable; // Handsontable features publicly accessible here

  constructor(element: HTMLElement, options: GridSettings) {
    const o = { ...this._baseGridSettings, ...options };
    this._hot = new Handsontable(element, o);
  }

  // common features for all tables
  public findReplace = (find: string, replace: string) => {
    //  ...
  };

  // common settings used by most tables
  private _baseTableSettings: GridSettings = {
    undo: false,
    autoColumnSize: true,
    autoRowSize: false,
    columns: [],
    // ...
  };
}

export class BlueTable extends BaseTable {
  constructor(element: HTMLElement, options: GridSettings) {
    super(element, options);
    this._hot.updateSettings(this._blueTableSettings);
  }

  public featureBlue = () => {
    this._hot.countRows(); // access HoT
    // ...
  };

  // settings used by blueTable only
  private _blueTableSettings: GridSettings = {
    // ...
  };
}

export class RedTable extends BaseTable {
  constructor(element: HTMLElement, options: GridSettings) {
    super(element, options);
    this._hot.updateSettings(this._redTableSettings);
  }

  public featureRed = () => {
    //  ...
  };

  // settings used by redTable only
  private _redTableSettings: GridSettings = {
    // ...
  };
}

Now it should be easy to test my custom features and the logic is encapsulated nicely,
This is used in a React application and I find it is a nice approach that works well.

Hi @mottosson

Thank you for the update and sharing your solution! I’m sure it will be helpful for other users looking for similar case.