From 04818ca0af1a25d9f1eb4482c9c2a69bb4f0a301 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Mon, 21 Dec 2020 18:11:58 -0500 Subject: [PATCH 1/2] add `process_callback_call` test with wrong current result, in the case where a callback has multiple outputs referencing the same component id --- test/callbacks.jl | 25 +++++++++++++++++++++++++ 1 file changed, 25 insertions(+) diff --git a/test/callbacks.jl b/test/callbacks.jl index 368b8c0..45d0e8b 100644 --- a/test/callbacks.jl +++ b/test/callbacks.jl @@ -120,6 +120,31 @@ end @test haskey(app.callbacks, Symbol("my-div.children")) @test app.callbacks[Symbol("my-div.children")].func("value", " value2") == "value value2" +end +@testset "callback! multi output same component id" begin + app = dash() + app.layout = html_div() do + dcc_input(id = "input-one", + placeholder = "text or number?") + dcc_input(id = "input-two", + placeholder = "") + end + callback!(app, Output("input-two","placeholder"), Output("input-two","type"), + Input("input-one","value")) do val1 + if val1 in ["text", "number"] + return "$val1 ??", val1 + end + return "invalid", nothing + end + @test length(app.callbacks) == 1 + @test haskey(app.callbacks, Symbol("..input-two.placeholder...input-two.type..")) + @test app.callbacks[Symbol("..input-two.placeholder...input-two.type..")].func("text") == ("text ??", "text") + @test Dash.process_callback_call(app, + Symbol("..input-two.placeholder...input-two.type.."), + [(id = "input-two", property = "placeholder"), + (id = "input-two", property = "type")], + [(value = "text",)], [])[:response] == Dict("input-two" => Dict(:type => "text")) + end @testset "callback! checks" begin From 02a148195d3bc4b22145876be8c5caac5dac9d0b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=C3=89tienne=20T=C3=A9treault-Pinard?= Date: Mon, 21 Dec 2020 17:45:19 -0500 Subject: [PATCH 2/2] push response item to `dep_id_string` sub-Dict ... when the `dep_id_string` is already present in the outer response Dict This makes callbacks with multiple output referencing the same component id update properly The failing test added in the previous commit is also fixed here --- src/handler/processors/callback.jl | 15 ++++++++++----- test/callbacks.jl | 3 ++- 2 files changed, 12 insertions(+), 6 deletions(-) diff --git a/src/handler/processors/callback.jl b/src/handler/processors/callback.jl index 4e61108..46c5fa5 100644 --- a/src/handler/processors/callback.jl +++ b/src/handler/processors/callback.jl @@ -20,11 +20,16 @@ function _push_to_res!(res, value, out::Vector) _push_to_res!.(Ref(res), value, out) end function _push_to_res!(res, value, out) - !(value isa NoUpdate) && push!(res, - dep_id_string(out.id) => Dict( - Symbol(out.property) => DashBase.to_dash(value) - ) - ) + if !(value isa NoUpdate) + id = dep_id_string(out.id) + prop = Symbol(out.property) + dashval = DashBase.to_dash(value) + if haskey(res, id) + push!(res[id], prop => dashval) + else + push!(res, id => Dict{Symbol, Any}(prop => dashval)) + end + end end _single_element_vect(e::T) where {T} = T[e] diff --git a/test/callbacks.jl b/test/callbacks.jl index 45d0e8b..c3c079c 100644 --- a/test/callbacks.jl +++ b/test/callbacks.jl @@ -143,7 +143,8 @@ end Symbol("..input-two.placeholder...input-two.type.."), [(id = "input-two", property = "placeholder"), (id = "input-two", property = "type")], - [(value = "text",)], [])[:response] == Dict("input-two" => Dict(:type => "text")) + [(value = "text",)], [])[:response] == Dict("input-two" => Dict(:type => "text", + :placeholder => "text ??")) end @testset "callback! checks" begin