BorisMoore / jsviews

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

Possible incompatibility of function.depends pattern with TypeScript #396

Closed BorisMoore closed 5 years ago

BorisMoore commented 6 years ago

See https://stackoverflow.com/a/47859851/1054484.

ClaudeVernier commented 6 years ago

Hello,

Thank you for your answers and for creating this issue, I did find a web site where I can create a working example in TypeScript! https://codepen.io/ClaudeVernier/pen/JMOJOR

In this pen, I tried to explain the issue with my latest findings, it looks like it might be Visual Studio that is wrong.

I can also provide files if useful for you.

Regards, Claude

BorisMoore commented 6 years ago

Thanks Claude. I will come back to this at some point, when I look more closely at TypeScript support for JsViews and JsRender. It's very helpful to have this example...

ClaudeVernier commented 6 years ago

Dear Boris, I hope you are doing well.

I am coming back to this project where the function .depends doesn't work for me in VS 2017 using TypeScript. Would you, by any chance, have some news that would bring light upon this issue ?

Thanks and regards, Claude VERNIER

BorisMoore commented 6 years ago

Hi Claude, Yes, thanks - I'm doing well. I am working on some major feature improvements in JsViews, and won't be able to get to the Typescript question for a while. I was only planning to look at Typescript support as a last step before (or just after) bringing out the V1.0. See https://github.com/BorisMoore/jsviews/issues/175. Sorry not to be able to get to it sooner...

BorisMoore commented 5 years ago

@ClaudeVernier

Hi Claude - I have finally completed work on V1.0 - to be published soon. I also have completed TypeScript declaration files for jsrender and jsviews:

Note that jsviews.js includes the code from jsrender.js, jquery.observable.js and jquery.views.js. So no need to load jquery.observable.js in your codpen sample. (See https://www.jsviews.com/#download)

Here is a fork of you codepen that includes the TypeScript declaration code, and fixes your issues.

https://codepen.io/borismoore/pen/wQmPoz

And here is another which tests loading jsrender and jsviews d.ts files from a server (you can replace with your own URLs):

https://codepen.io/borismoore/pen/wQmXRB

After publishing V1.0 I will publish the d.ts files to definitelyTyped.org.

The fix for your sample was to move the setting of .depends to before calling tmpl.link:

(this.GetName as JsViews.GetSet).depends = "~root.activeLanguage";
// Or  (this.GetName as JsViews.GetSet).depends = [this, "activeLanguage"];

tmpl.link("#optionsTmpl", this);

BTW the casting of this.GetName to as JsViews.GetSet is to avoid the TypeScript 'error'. But getting the error does not really matter since the compiled .js is still correct, and works just the same...

Let me know if you see other issues (e.g. with the TypeScript definitions)...

BorisMoore commented 5 years ago

Closing this issue, since it is not a JsViews bug. (Also it seems to be fixed by the suggested cchange to your code).

ClaudeVernier commented 5 years ago

Dear Boris,

It has bring me so much joy when you answered me !!! Thanks a lot !! 🙂 It took me some time but I rewrote my game, using your solution and waited that it is a bit more advanced before showing it.

It is still far from done but here it is, if you would like to have a look: https://unchartedwaters3.azurewebsites.net/

You land on the Atlantic sea near the town of Lorient in France.

The orange button on top-left corner opens the options where you can change language and navigate to other towns, kind of a cheat mode.

You can also click on the Lorient city. Shops gets highlighted when mouseover is triggered. Clicking on the "Old' Shop" on the left side brings up the logic I did to enable users to buy products and using JSView, I update the cargo load, the amount of gold and the shopkeeper inventory with one click of the JQuery Slider !!!

There is still a lot of work but I'm very happy that I was able to build this screen !!

I hope that all is going well for you, thank you for JSViews and TypeScript extensions.

Kind regards, Claude


De : Boris Moore notifications@github.com Envoyé : vendredi 23 novembre 2018 07:39 À : BorisMoore/jsviews Cc : ClaudeVernier; Comment Objet : Re: [BorisMoore/jsviews] Possible incompatibility of function.depends pattern with TypeScript (#396)

Hi Claude - I have finally completed work on V1.0 - to be published soon. I also have completed TypeScript declaration files for jsrender and jsviews.

Note that jsviews.js includes the code from jsrender.js, jquery.observable.js and jquery.views.js. So no need to load jquery.observable.js in your codpen sample. (See https://www.jsviews.com/#download)

Here is a fork of you codepen that includes the TypeScript declaration code, and fixes your issues.

https://codepen.io/borismoore/pen/wQmPoz

And here is another which tests loading jsrender and jsviews d.ts files from a server (you can replace with your own URLs):

https://codepen.io/borismoore/pen/wQmXRB

After publishing V1.0 I will publish the d.ts files to definitelyTyped.org.

The fix for your sample was to move the setting of .depends to before calling tmpl.link:

(this.GetName as JsViews.GetSet).depends = "~root.activeLanguage"; // Or (this.GetName as JsViews.GetSet).depends = [this, "activeLanguage"];

tmpl.link("#optionsTmpl", this);

BTW the casting of this.GetName to as JsViews.GetSet is to avoid the TypeScript 'error'. But getting the error does not really matter since the compiled .js is still correct, and works just the same...

Let me know if you see other issues (e.g. with the TypeScript definitions)...

— You are receiving this because you commented. Reply to this email directly, view it on GitHubhttps://github.com/BorisMoore/jsviews/issues/396#issuecomment-441164873, or mute the threadhttps://github.com/notifications/unsubscribe-auth/ADicLQc9crUr2LiUcprlWQnHOqyHIaE1ks5ux5gtgaJpZM4RTPQF.

BorisMoore commented 5 years ago

Thanks Claude, glad to hear back from you...

jonathantisseau commented 5 years ago

Hi, I know this issue is closed but I found it while searching the same issue. Another solution to your problem is to go with a decorator :

/**
 * JsViews Depends decorator
 * Add the value to the depend property of the target
 * Even if it can work with a getter, JsViews doesn't allow it and, even if the initial display works, it won't be refreshed.
 * @param {string|any[]|JsViews.dependsFunction} value The depends path(s) or function
 */
export function depends(value: string | any[] | JsViews.dependsFunction) {
    return function (target: any, propertyKey: string, descriptor: any) {
        if (!descriptor) {
            descriptor = Object.getOwnPropertyDescriptor(target, propertyKey);
        }
        let func = descriptor.get || descriptor.value;
        if (func && typeof func === "function") {
            func.depends = value;
        }
    };
}

An then you can do something like this

class UnchartedGame {
    ...
    @depends("~root.activeLanguage")
    // or @depends((data, callback) => ["~root.activeLanguage"])
    GetName(harbor: IHarbor): any {
        return harbor.name[(this as IJSViewsContextHolder).ctx.root.activeLanguage];
    }
    ...
}

The main advantage of this solution is to keep the function definition and its depends definition together. The inconvenients are that you can't use variables in this context and you can't use a getter because JsViews doesn't allow it.

Here is the working codepen : https://codepen.io/jonathantisseau/pen/NWKRvOQ

I'm new to JsViews so I haven't tested it in every possible ways.

BorisMoore commented 5 years ago

Thanks for the suggestion and code, @jonathantisseau!