JuliaGizmos / Interact.jl

Interactive widgets to play with your Julia code
Other
522 stars 77 forks source link

Interact.jl widgets not getting rendered on jupyter-notebook #372

Closed agarie closed 3 years ago

agarie commented 3 years ago

Hi! I'm just getting started with Interact, so I'm sorry if this issue is due to my inexperience with the Julia ecosystem.

I have a notebook with the following code:

using Interact
s = slider(0:.1:1,label="Slider X:")

resulting in the following:

Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Scope(Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :label), Any["Slider X:"], Dict{Symbol,Any}(:className => "interact ",:style => Dict{Any,Any}(:padding => "5px 10px 0px 10px")))], Dict{Symbol,Any}(:className => "interact-flex-row-left")), Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :input), Any[], Dict{Symbol,Any}(:max => 11,:min => 1,:attributes => Dict{Any,Any}(:type => "range",Symbol("data-bind") => "numericValue: index, valueUpdate: 'input', event: {change: function (){this.changes(this.changes()+1)}}","orient" => "horizontal"),:step => 1,:className => "slider slider is-fullwidth",:style => Dict{Any,Any}()))], Dict{Symbol,Any}(:className => "interact-flex-row-center")), Node{WebIO.DOM}(WebIO.DOM(:html, :div), Any[Node{WebIO.DOM}(WebIO.DOM(:html, :p), Any[], Dict{Symbol,Any}(:attributes => Dict("data-bind" => "text: formatted_val")))], Dict{Symbol,Any}(:className => "interact-flex-row-right"))], Dict{Symbol,Any}(:className => "interact-flex-row interact-widget")), Dict{String,Tuple{Observables.AbstractObservable,Union{Nothing, Bool}}}("changes" => (Observable{Int64} with 1 listeners. Value:
0, nothing),"index" => (Observable{Any} with 2 listeners. Value:
6, nothing)), Set{String}(), nothing, Asset[Asset("js", "knockout", "/Users/caj/.julia/packages/Knockout/IP1uR/src/../assets/knockout.js"), Asset("js", "knockout_punches", "/Users/caj/.julia/packages/Knockout/IP1uR/src/../assets/knockout_punches.js"), Asset("js", nothing, "/Users/caj/.julia/packages/InteractBase/sOe2Z/src/../assets/all.js"), Asset("css", nothing, "/Users/caj/.julia/packages/InteractBase/sOe2Z/src/../assets/style.css"), Asset("css", nothing, "/Users/caj/.julia/packages/Interact/SbgIk/src/../assets/bulma_confined.min.css")], Dict{Any,Any}("changes" => Any[WebIO.JSString("(function (val){return (val!=this.model[\"changes\"]()) ? (this.valueFromJulia[\"changes\"]=true, this.model[\"changes\"](val)) : undefined})")],"index" => Any[WebIO.JSString("(function (val){return (val!=this.model[\"index\"]()) ? (this.valueFromJulia[\"index\"]=true, this.model[\"index\"](val)) : undefined})")]), WebIO.ConnectionPool(Channel{Any}(sz_max:32,sz_curr:0), Set{AbstractConnection}(), Base.GenericCondition{Base.AlwaysLockedST}(Base.InvasiveLinkedList{Task}(Task (runnable) @0x00000001162e3610, Task (runnable) @0x00000001162e3610), Base.AlwaysLockedST(1))), WebIO.JSString[WebIO.JSString("function () {\n    var handler = (function (ko, koPunches) {\n    ko.punches.enableAll();\n    ko.bindingHandlers.numericValue = {\n        init: function(element, valueAccessor, allBindings, data, context) {\n            var stringified = ko.observable(ko.unwrap(valueAccessor()));\n            stringified.subscribe(function(value) {\n                var val = parseFloat(value);\n                if (!isNaN(val)) {\n                    valueAccessor()(val);\n                }\n            });\n            valueAccessor().subscribe(function(value) {\n                var str = JSON.stringify(value);\n                if ((str == \"0\") && ([\"-0\", \"-0.\"].indexOf(stringified()) >= 0))\n                     return;\n                 if ([\"null\", \"\"].indexOf(str) >= 0)\n                     return;\n                stringified(str);\n            });\n            ko.applyBindingsToNode(\n                element,\n                {\n                    value: stringified,\n                    valueUpdate: allBindings.get('valueUpdate'),\n                },\n                context,\n            );\n        }\n    };\n    var json_data = {\"formatted_vals\":[\"0.0\",\"0.1\",\"0.2\",\"0.3\",\"0.4\",\"0.5\",\"0.6\",\"0.7\",\"0.8\",\"0.9\",\"1.0\"],\"changes\":WebIO.getval({\"name\":\"changes\",\"scope\":\"5742539691840127748\",\"id\":\"14016215829043600783\",\"type\":\"observable\"}),\"index\":WebIO.getval({\"name\":\"index\",\"scope\":\"5742539691840127748\",\"id\":\"11122984423837624543\",\"type\":\"observable\"})};\n    var self = this;\n    function AppViewModel() {\n        for (var key in json_data) {\n            var el = json_data[key];\n            this[key] = Array.isArray(el) ? ko.observableArray(el) : ko.observable(el);\n        }\n        \n        [this[\"formatted_val\"]=ko.computed(    function(){\n        return this.formatted_vals()[parseInt(this.index())-(1)];\n    }\n,this)]\n        [this[\"changes\"].subscribe((function (val){!(this.valueFromJulia[\"changes\"]) ? (WebIO.setval({\"name\":\"changes\",\"scope\":\"5742539691840127748\",\"id\":\"14016215829043600783\",\"type\":\"observable\"},val)) : undefined; return this.valueFromJulia[\"changes\"]=false}),self),this[\"index\"].subscribe((function (val){!(this.valueFromJulia[\"index\"]) ? (WebIO.setval({\"name\":\"index\",\"scope\":\"5742539691840127748\",\"id\":\"11122984423837624543\",\"type\":\"observable\"},val)) : undefined; return this.valueFromJulia[\"index\"]=false}),self)]\n        \n    }\n    self.model = new AppViewModel();\n    self.valueFromJulia = {};\n    for (var key in json_data) {\n        self.valueFromJulia[key] = false;\n    }\n    ko.applyBindings(self.model, self.dom);\n}\n);\n    (WebIO.importBlock({\"data\":[{\"name\":\"knockout\",\"type\":\"js\",\"url\":\"/assetserver/11f507ac8a8d4235efeb3c82e28f98bd7b561322-knockout.js\"},{\"name\":\"knockout_punches\",\"type\":\"js\",\"url\":\"/assetserver/9e94a58ea3cc98119b896fcd872afaffc7e25b8f-knockout_punches.js\"}],\"type\":\"async_block\"})).then((imports) => handler.apply(this, imports));\n}\n")])], Dict{Symbol,Any}(:className => "field interact-widget"))

I'm on macOS 10.15.6 with Julia 1.5 installed with Homebrew. I installed the nbextension as instructed in the README as well. My configurations is:

$ jupyter --version
jupyter core     : 4.6.3
jupyter-notebook : 6.1.3
qtconsole        : not installed
ipython          : 7.17.0
ipykernel        : 5.3.4
jupyter client   : 6.1.6
jupyter lab      : not installed
nbconvert        : 5.6.1
ipywidgets       : 7.5.1
nbformat         : 5.0.7
traitlets        : 4.3.3

$ jupyter nbextension list
Known nbextensions:
  config dir: /Users/caj/.jupyter/nbconfig
    notebook section
      webio-jupyter-notebook  enabled
      - Validating: OK
      jupyter-js-widgets/extension  enabled
      - Validating: OK
  config dir: /usr/local/etc/jupyter/nbconfig
    notebook section
      jupyter-js-widgets/extension  enabled
      - Validating: OK

What could be causing this? Do you have any suggestion as to what I could do to debug this? I'll be happy to give any more information if necessary.

shashi commented 3 years ago

Did you restart Jupyter server and open a new notebook and try?

agarie commented 3 years ago

@shashi Yes. I reproduced this issue with a new notebook (after restarting the Jupyter server) in which the only content were the cells containing the code shown on my initial post.

lysogeny commented 3 years ago

I encountered a possibly similar issue.

First of all, I noticed that the library worked when I ran it on my local machine. The trouble started when I tried to use Interact.jl on my server's jupyter notebook server. There I have a jupyter server behind an nginx reverse proxy on /jupyter. Similarly to agarie's issue, buttons and sliders just wouldn't show up.

In my browser's devtools I noticed that several requests return 404, e.g. for http://{server}/assetserver/86a580a22f01186f16f4a4ebde37669899bd7bbd-knockout.js. This makes sense as nginx is not serving anything on /assetserver, and it should be /jupyter/assetserver[...].

I don't know if it is possible to configure this somewhere, or if the c.NotebookApp.base_url from jupyter's config can be used. I haven't looked too far into this, however I suspect that this problem might actually a WebIO.jl problem.

For now I have added the following temporary fix into my nginx config:

server {
    rewrite ^/assetserver/(.*) /jupyter/assetserver/$1 break;
    [...]
}
matthijscox commented 3 years ago

I encountered the exact same issue, I haven't solved it fully yet, but it seems related to (automatically) rendering WebIO nodes. When I explicitly import WebIO, I can make it show the slider:

image

However, this doesn't solve all my Interact issues. observe(s) doesnt seem to work, @manipulate doesn't work either for me

matthijscox commented 3 years ago

Ok I see now that my Interact and InteractBase builds are failing. It fails to download the css for Interact:

image

Interact issue 333 seems related. Also I'm now reading Julia Discourse: Problem with curl.exe

matthijscox commented 3 years ago

Ok fixed it by getting the builds working. I followed the solution from the [discourse post] to get curl.exe working (https://discourse.julialang.org/t/problem-with-curl-exe-windows-and-package-installation/29525/53):

  1. Open a command prompt, and type echo %APPDATA% to get the personal app data folder.
  2. Create an empty file called _curlrc in the app data folder.
  3. Write insecure on that file and save.
  4. import Pkg; Pkg.build("Interact")

Now the tutorial works directly:

image

agarie commented 3 years ago

Ok fixed it by getting the builds working. I followed the solution from the [discourse post] to get curl.exe working (https://discourse.julialang.org/t/problem-with-curl-exe-windows-and-package-installation/29525/53):

1. Open a command prompt, and type echo %APPDATA% to get the personal app data folder.

2. Create an empty file called _curlrc in the app data folder.

3. Write insecure on that file and save.

4. import Pkg; Pkg.build("Interact")

I did the same thing on macOS by creating a .curlrc on $HOME with insecure written on it then rebuilding Interact. It worked as well. Please remember to delete that .curlrc after that, tho. :P

I'm closing this issue now.