Skip to content

Commit a4efcab

Browse files
move indexing from Dash.jl
1 parent c2a9d6b commit a4efcab

File tree

2 files changed

+48
-11
lines changed

2 files changed

+48
-11
lines changed

src/components.jl

+29-6
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
to_dash(t::Any) = t
22

3-
struct Component
3+
struct Component
44
name ::String
55
type ::String
66
namespace ::String
@@ -9,9 +9,9 @@ struct Component
99
wildcard_regex ::Union{Nothing, Regex}
1010
function Component(name::String, type::String, namespace::String,
1111
props::Vector{Symbol}, wildcard_props::Vector{Symbol}; kwargs...)
12-
12+
1313
available_props = Set{Symbol}(props)
14-
wildcard_regex::Union{Nothing, Regex} = nothing
14+
wildcard_regex::Union{Nothing, Regex} = nothing
1515
if !isempty(wildcard_props)
1616
wildcard_regex = Regex(join(string.(wildcard_props), "|"))
1717
end
@@ -30,13 +30,36 @@ get_available_props(comp::Component) = getfield(comp, :available_props)
3030
get_wildcard_regex(comp::Component) = getfield(comp, :wildcard_regex)
3131
get_props(comp::Component) = getfield(comp, :props)
3232

33-
function Base.getproperty(comp::Component, prop::Symbol)
33+
const VecChildTypes = Union{NTuple{N, Component} where {N}, Vector{<:Component}}
34+
35+
function Base.getindex(component::Component, id::AbstractString)
36+
component.id == id && return component
37+
hasproperty(component, :children) || return nothing
38+
cc = component.children
39+
return if cc isa Union{VecChildTypes, DashBase.Component}
40+
cc[id]
41+
elseif cc isa AbstractVector
42+
fcc = identity.(filter(x->hasproperty(x, :id), cc))
43+
isempty(fcc) ? nothing : fcc[id]
44+
else
45+
nothing
46+
end
47+
end
48+
function Base.getindex(children::VecChildTypes, id::AbstractString)
49+
for element in children
50+
element.id == id && return element
51+
el = element[id]
52+
el !== nothing && return el
53+
end
54+
end
55+
56+
function Base.getproperty(comp::Component, prop::Symbol)
3457
!Base.hasproperty(comp, prop) && error("Component $(get_name(comp)) has no property $(prop)")
3558
props = get_props(comp)
3659
return haskey(props, prop) ? props[prop] : nothing
3760
end
3861

39-
function Base.setproperty!(comp::Component, prop::Symbol, value)
62+
function Base.setproperty!(comp::Component, prop::Symbol, value)
4063
!Base.hasproperty(comp, prop) && error("Component $(get_name(comp)) has no property $(prop)")
4164
props = get_props(comp)
4265
push!(props, prop=>to_dash(value))
@@ -56,4 +79,4 @@ Base.propertynames(comp::Component) = collect(get_available_props(comp))
5679
push_prop!(component::Component, prop::Symbol, value) = push!(component.props, prop=>to_dash(value))
5780

5881
JSON3.StructTypes.StructType(::Type{DashBase.Component}) = JSON3.StructTypes.Struct()
59-
JSON3.StructTypes.excludes(::Type{DashBase.Component}) = (:name, :available_props, :wildcard_regex)
82+
JSON3.StructTypes.excludes(::Type{DashBase.Component}) = (:name, :available_props, :wildcard_regex)

test/components.jl

+19-5
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ using JSON3
55
test_comp = Component("html_div", "Div", "dash_html_components",
66
[:children, :id, :n_clicks],
77
[Symbol("data-"), Symbol("aria-")];
8-
id = 10,
8+
id = 10,
99
n_clicks = 1
1010
)
11-
11+
1212
@test get_name(test_comp) == "html_div"
1313
@test get_type(test_comp) == "Div"
1414
@test get_namespace(test_comp) == "dash_html_components"
@@ -26,7 +26,7 @@ using JSON3
2626
@test_throws ErrorException Component("html_div", "Div", "dash_html_components",
2727
[:children, :id, :n_clicks],
2828
[Symbol("data-"), Symbol("aria-")];
29-
id = 10,
29+
id = 10,
3030
key = 1
3131
)
3232
json = JSON3.write(test_comp)
@@ -42,7 +42,7 @@ end
4242
test_comp = Component("html_div", "Div", "dash_html_components",
4343
[:children, :id, :n_clicks],
4444
Symbol[];
45-
id = 10,
45+
id = 10,
4646
n_clicks = 1
4747
)
4848

@@ -54,4 +54,18 @@ end
5454

5555
@test_throws ErrorException test_comp.var"data-id" = 20
5656
@test_throws ErrorException test_comp.aaaaa
57-
end
57+
end
58+
59+
@testset "Index by id" begin
60+
layout = html_div() do
61+
dcc_input(id = "my-id", value="initial value", type = "text"),
62+
html_div(id = "my-div", children = [
63+
html_div(children = []),
64+
"string",
65+
html_div(id = "target")
66+
]),
67+
html_div(id = "my-div2")
68+
end
69+
@test layout["target"].id == "target"
70+
@test layout["ups"] === nothing
71+
end

0 commit comments

Comments
 (0)