0

I'm trying to build a simple binding framework in JavaScript. I want to have a model with getters and setters that keeps everything consistent, i.e. updating one property can affect others and then JavaScript that then binds that to fields in the page.

The problem I'm having is I need to add some extra code to the setters on the model when I bind so that updating a property executes code that's already in the setter to keep the model consistent and then update the bound input(s).

I thought about renaming the existing property and adding a new property with the original name which could set the original property and update the input but I can't see a way to rename the field.

Is there any way to either rename a property with a getter/setter, modify a setter or get the code in a setter so I can copy that?

Alternatively, is there any other way to achieve what I'm trying to do?

I'm trying to keep separation between business logic (the model) and the UI (the html) without requiring the person writing the model to have to think about the UI / binding at all.

I also don't want to use any of the big libraries like Angular or Knockout as they're a lot of code to include in the page for pretty limited requirements, plus this is a project we've been developing / maintaining for 20 years+ so we don't want to be using a library that has a history of massive breaking changes (Angular).

We currently need to support IE10/11 and modern versions of Chrome / Edge / Firefox / Safari (iOS and Mac). However, if there's something that doesn't support all of these, we're open to doing a "nice" way with a "nasty" fallback until we can drop IE support.

If it makes any difference, we are using TypeScript to write the JavaScript.

Edit: Since submitting my question, I've found this. It says you can rename a property with:

Object.defineProperty(o, new_key, Object.getOwnPropertyDescriptor(o, old_key));
delete o[old_key];

This is working for renaming simple variable type properties but not for renaming properties with getters and setters. I'm not sure why, although my properties with getters / setters return false when I do hasOwnProperty on them.

Edit2: Turns out that TypeScript was adding the properties against the prototype instead of the object and this is why they weren't accessible. I called Object.getOwnPropertyDescriptor(o.__proto__, old_key) instead and this gave me the descriptor I needed.

Mog0
  • 1,689
  • 1
  • 16
  • 40
  • Have a look at [How do data-binding works in angularjs](https://stackoverflow.com/a/9693933/2417602) you might get some ideas. – vikscool Aug 08 '18 at 09:15
  • Could you post some code to illustrate what you are trying to achieve? – FedericoG Aug 08 '18 at 09:29
  • Agreeing with @FedericoG, this isn't a simple answer and posting some sample code would help us to help you. As a side note, you could register custom `emitters` on your props that have listeners to reflect the modified data. Perhaps you could try to reflect `INotifiyPropertyChanged` from `C#` into your code? – James Gould Aug 08 '18 at 09:33

1 Answers1

0

I've found that you can edit / extend the setter by doing the following:

var propDescriptor = Object.getOwnPropertyDescriptor(model, key);

propDescriptor.set = function (value) {
    setter.call(model, value);
    //Do extra stuff here
}

Object.defineProperty(model, key, propDescriptor);

This means that the property still maintains consistency while allowing you to extend it to update the bound input field.

Mog0
  • 1,689
  • 1
  • 16
  • 40