BorisMoore / jsviews

Interactive data-driven views, MVVM and MVP, built on top of JsRender templates
http://www.jsviews.com/#jsviews
MIT License
855 stars 130 forks source link

Automatically re-evaluate helper functions #319

Closed markibanez closed 8 years ago

markibanez commented 8 years ago

Hi @BorisMoore,

I was wondering if there was a way to automatically re-evaluate the values from helper functions. I have something like data-link=css-background-color{:~get_active_tool_option(value_path)} . where value_path is a path to a property that is updated observably behind the scenes. The aim is to have the value returned by the helper function automatically update when the property is updated. I attempted doing this via helper.depends but it did not work for me. The property is getting updated but the data-linked helper object is not updated.

Thanks in advance.

BorisMoore commented 8 years ago

That should work. For example see http://www.jsviews.com/#samples/editable/tags

<tr class="hover" data-link="css-background-color{:~bgColor()}">

function bgColor() {
  return this.ctx.root.selectedIndex === this.index
      ? "yellow"
      : (this.index%2 ? "#fdfdfe" : "#efeff2");
}
bgColor.depends = ["#index", "~root.selectedIndex"];

Selecting a new row does update the background color.

In fact if you pass in the parameter explicitly, you don't even need the depends. Change it to the following and it still works:

<tr class="hover" data-link="css-background-color{:~bgColor(~root.selectedIndex)}">

function bgColor() {
  return this.ctx.root.selectedIndex === this.index
      ? "yellow"
      : (this.index%2 ? "#fdfdfe" : "#efeff2");
}

So there must be some other issue in your code... You could create a jsfiddle, if you can't figure it out...

markibanez commented 8 years ago

Hi Boris,

Sorry I didn't explain clearly. I'm trying to pass a "string path" to the property to the helper function. The helper function actually uses some other code to get the actual property from a string path. Sort of the reverse of $.observable().setProperty().

Here's my helper function:

//helper function
function getActiveToolOption(path) {
    return Object.byString(model, path);
}

//function that gets the object property from a string path
Object.byString = function(o, s) {
    s = s.replace(/\[(\w+)\]/g, '.$1'); // convert indexes to properties
    s = s.replace(/^\./, '');           // strip a leading dot
    var a = s.split('.');
    for (var i = 0, n = a.length; i < n; ++i) {
        var k = a[i];
        if (k in o) {
            o = o[k];
        } else {
            return;
        }
    }
    return o;
}

So I think the problem is that, although the actual property is being changed, the fact that I'm passing a static string parameter is the reason that the helper function isn't being "updated" or called again.

So I think that begs the question, is there a way of manually forcing the helper function to update? Also, in case there is a way to do it, are there any performance considerations?

Thanks again :)

BorisMoore commented 8 years ago

Being a string parameter should not make a difference. Not sure what you mean by static.

Can you create a small jsfiddle showing what you are doing - with a button in which you 'update the string property'?

There are ways of relinking, etc. but it would help to have an jsfiddle example to work from so I can suggest...

markibanez commented 8 years ago

Hi Boris,

Here's a jsfiddle to show you what I mean: http://jsfiddle.net/markibanez/4hg2960x/3/

Thanks :)

BorisMoore commented 8 years ago

Hi Mark,

OK - well here are three alternatives:

http://jsfiddle.net/4hg2960x/4/ uses:

getColorByPath.depends = "some_object.selected_color";

http://jsfiddle.net/4hg2960x/5/ uses:

$.view("#tgt").refresh(true);

http://jsfiddle.net/4hg2960x/6/ uses:

$.unlink("#tgt");
$.link("css-background-color{:~get_selected_color(color_property_path)}", "#tgt", model);

Does that cover your scenarios?

markibanez commented 8 years ago

Aww yeah! Thank you @BorisMoore exactly what I needed.