JuliaGizmos / Escher.jl

Composable Web UIs in Julia
https://juliagizmos.github.io/Escher.jl
Other
335 stars 63 forks source link

Daisy Chaining Inputs from one Widget to Another #70

Closed mturok closed 8 years ago

mturok commented 8 years ago

Shashi,

Is there currently a way to a daisy chain signals from one widget to another?

That is: if I have an Input into one widget, that itself creates an input used by another widget.

Getting error messages about: push! called when another signal is still updating

It looks like there was a reference to something like this in an issue raised by @Keno on https://github.com/JuliaLang/Reactive.jl/issues/62.

Any suggestions here or workarounds?

Thanks, Michael

shashi commented 8 years ago

Is something like

signal1 = Input(0)
signal2 = Input(0)

vbox(
    slider(0:10) >>> signal1,
    lift(x -> slider(0:2x) >>> signal2, signal1),
    signal1,
    signal2,
)

what you are looking for? Would be great if you can post a code example.

If you wanted to keep signal2 within the correct bounds, you could lift on both signal1 and signal2 to do that.

Everything is good as long as you don't try to call push! inside of a lifted signal. Keno's issue is encountered when when push! is called when another lift is blocking on something on a different task. We'll figure out the right way to fix that soon.

shashi commented 8 years ago

If you wanted two widgets to be in sync:

signal1 = Input(0)
lift(signal1) do value
  vbox(
    slider(0:10, value=value) >>> signal1,
    slider(0:10, value=value) >>> signal1,
  )
end
mdcfrancis commented 8 years ago

Replying on behalf of of Michael, given the below example I get the following error type: anonymous: in apply, expected Function, got Sample' I assume there is something obvious we are doing wrong.

function main(window)   
    push!(window.assets, "widgets")
    push!(window.assets, "codemirror")
    def = """
    code 
    """
    form_signal1 = Input(Dict())
    form_signal2 = Input(Dict())

    function form( def )
        s = sampler()
        editor = watch!(s, codemirror( def )) |> size(20vw, 30vh)
        submit = trigger!(s, button("Next"))
        form = plugsampler(s, vbox(editor, vskip(1em), submit))                 
        return form;
    end

    function mywidget( data )
        return plaintext( data )
    end
    vbox(        
        form( def ) >>> form_signal1,        
        lift( fd -> form( fd ) >>> form_signal2, form_signal1),
        lift( data -> mywidget( data ), form_signal2 ),        
        form_signal1,
        form_signal2        
    )
end

Initially we had a push! in the signal handler to chain the events ( this doesn't work ) so this is a re-write. If I remove the second lift

vbox(        
    form( def ) >>> form_signal1,             
    lift( data -> mywidget( data ), form_signal1 ),        
    form_signal1,
    form_signal2        
)

This works, but it is the chain we are looking for

mturok commented 8 years ago

Actually, we got it working....your snippet above helped tremendously!

(Turns out the issue is with the lexical scoping: the form variable got redefined from a Function to a Sample inside of the form() function).

Regards!

shashi commented 8 years ago

Great! :) those two functions need not be inside main anyway.

On Wed, Aug 26, 2015, 2:10 AM Michael Turok notifications@github.com wrote:

Closed #70 https://github.com/shashi/Escher.jl/issues/70.

— Reply to this email directly or view it on GitHub https://github.com/shashi/Escher.jl/issues/70#event-392125800.