jupyter / declarativewidgets

[RETIRED] Jupyter Declarative Widget Extension
http://jupyter.org/declarativewidgets/docs.html
Other
120 stars 38 forks source link

Feature Request / Question: general `urth-core-var` element to pull value from kernel #534

Open haobibo opened 7 years ago

haobibo commented 7 years ago

Currently, urth-core-dataframe is an urth element to bind to or "pull" a DataFrame variable in kernel. For example, when there exists a DataFrame variable named aDataFrame in a Python kernel, then user can use these code to bind aDataFrame from back-end kernel to front-end channel as df:

<template is="urth-core-bind">
    <urth-core-dataframe id="df" ref="aDataFrame" value="df" auto></urth-core-dataframe>
<tmplate>

This is very useful and convenient when users are send DataFrame variables from back-end kernel to front-end. However, in many circumstances, users need to send a variable with a different data type, for instance, just a String (str, in any format, e.g.: JSON, XML, etc.), and then the string will be consumed by another front-end element. As an example, I am currently working on an GraphViz(http://mdaines.github.io/viz.js/) element, which consumes a string that is in the format of dot.

Surely user can use declarativewidgets.channel().set('var_name', var_value) to pass it to front-end channel. But I guess it wold be more convenient to create an urth-core-var dom element to allow users to bind/"pull" value from back-end kernel to front-end channel.

As an alternative, a quick but not-elegant solution is:

def get_var(x):
    r = globals().get(x, None)
    dw.channel().set(x, r)
    return r

and

%%html
<template is="urth-core-bind">
    <urth-core-function ref="get_var" arg-x='var_name' result='var_name' auto>
        <button>get/update Variabel</button>
    </urth-core-function>
    Variable Value:<span>{{var_name}}</span>
</template>

I wonder is there any existing and elegant mechanism in current version of declarativewidgets that meets such needs, or shall we create a general urth-core-var element to allow user bind a general variable (using str() or repr() to serialize) more conveniently, for example:

%%html
<template is="urth-core-bind">
    <urth-core-var ref="var_name" auto></urth-core-var>
    Variable Value:<span>[[var_name]]</span>
</template>

Even if this is a one-way binding (only pull from back-end kernel to front-end channel and cannot be updated from front-end channel to back-end kernel), it will also be very useful.

lbustelo commented 7 years ago

@haobibo This is already supported as part of channel().set( name, value) api in the kernel side. The variable will then be available to read and modify in the template. See examples at https://github.com/jupyter-incubator/declarativewidgets/blob/master/etc/notebooks/examples/urth-core-channel.ipynb.

Let me know if this fulfills your requirements.

haobibo commented 7 years ago

@lbustelo I agree that using channel().set(var_name, var_value) is a solution, as I mentioned in my post: third line of get_var(). But it is an "imperative" way (hard code in Python/R/Scala), not a "declarative" way (code in HTML).

For example, when passing a DataFrame from kernel to channel, I can also serialize it in Python/R/Scala, then using an imperative way (like channel().set(dataframe_name, dataframe_serialized_value)), and then no <urth-core-dataframe> with be needed. But this way requires users to write code that is intrusive to business logic code that handles with data. This is intrusive because users have to import declarativewidgets and channel().set(). While using <urth-core-dataframe> is a declarative way that avoids changes in users' Python/R/Scala code.

I think key idea of declarativewidgets is to decouple front-code (HTML and web components) from back-end code (Python/R/Scala), such that html code can be re-used. Assume a user change his back-end code from Python to Scala, as long as a global variable (say dataframe_viz_bar) remains unchanged, then the front-end code needs no change, and he doesn't need to write code like channel().set() in both Python and Scala.

So, I suggest that we can either generalize the <urth-core-dataframe> to <urth-core-var>, or create a new element that holds String type data, say <urth-core-string>.

lbustelo commented 7 years ago

@haobibo I rather create a new element for simpler types than generalize dataframe. I would welcome the PR and if you need guidance... let me know.

haobibo commented 7 years ago

@lbustelo OK, I will try to draft one or more elements. What about starting with elements like <urth-core-string> or <urth-core-json>, do you have any suggestions?