Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 5 additions & 1 deletion src/Elements.jl
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@ export root, elem, vm, @if, @else, @elseif, @for, @text, @bind, @data, @on, @cli
# deprecated exports
export @iif, @els, @elsiif, @recur

export @jsexpr, JSExpr, js_quote_replace, ∥, ∧
export @jsexpr, JSExpr, js_quote_replace, ∥, ∧, jse_str

export stylesheet, kw_to_str
export add_plugins, remove_plugins
Expand Down Expand Up @@ -484,6 +484,10 @@ macro jsexpr(expr)
:(JSExpr($ex))
end

macro jse_str(expr)
JSExpr(expr)
end

"""
@if(expr)

Expand Down
10 changes: 5 additions & 5 deletions src/ReactiveTools.jl
Original file line number Diff line number Diff line change
Expand Up @@ -1409,12 +1409,12 @@ function vue_options(hook_type, args...)
expr = args[1]
quote
let M = Stipple.@type
Stipple.$(Symbol("js_$hook_type"))(::M) = $expr
Stipple.$(Symbol("js_$hook_type"))(::Type{<:M}) = $expr
end
end |> esc
elseif length(args) == 2
T, expr = args[1], args[2]
esc(:(Stipple.$(Symbol("js_$hook_type"))(::$T) = $expr))
esc(:(Stipple.$(Symbol("js_$hook_type"))(::Type{<:$T}) = $expr))
else
error("Invalid number of arguments for vue options")
end
Expand Down Expand Up @@ -1527,7 +1527,7 @@ macro client_data(expr)

esc(quote
let M = Stipple.@type
Stipple.client_data(::M) = $output
Stipple.client_data(::Type{<:M}) = $output
end
end)
end
Expand All @@ -1544,7 +1544,7 @@ macro client_data(M, expr)
push!(output.args, e)
end

:(Stipple.client_data(::$(esc(M))) = $(esc(output)))
:(Stipple.client_data(::Type{<:$(esc(M))}) = $(esc(output)))
end

macro add_client_data(expr)
Expand All @@ -1563,7 +1563,7 @@ macro add_client_data(expr)
let M = Stipple.@type
cd_old = Stipple.client_data(M())
cd_new = $output
Stipple.client_data(::M) = merge(d1, d2)
Stipple.client_data(::Type{<:M}) = merge(d1, d2)
end
end)
end
Expand Down
74 changes: 41 additions & 33 deletions src/stipple/jsmethods.jl
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
"""
function js_methods(app::T) where {T<:ReactiveModel}
function js_methods(::Type{<:T}) where {T<:ReactiveModel}

Defines js functions for the `methods` section of the vue element.
Expected result types of the function are
Expand All @@ -12,7 +12,7 @@ Expected result types of the function are
### Example 1

```julia
js_methods(::MyDashboard) = \"\"\"
js_methods(::Type{<:MyDashboard}) = \"\"\"
mysquare: function (x) {
return x^2
}
Expand All @@ -23,18 +23,17 @@ js_methods(::MyDashboard) = \"\"\"
```
### Example 2
```
js_methods(::MyDashboard) = Dict(:f => "function(x) { console.log('x: ' + x) })
js_methods(::Type{<:MyDashboard}) = Dict(:f => "function(x) { console.log('x: ' + x) })
```
### Example 3
```
js_greet() = :greet => "function(name) {console.log('Hello ' + name)}"
js_bye() = :bye => "function() {console.log('Bye!')}"
js_methods(::MyDashboard) = [js_greet, js_bye]
js_methods(::Type{<:MyDashboard}) = [js_greet, js_bye]
```
"""
function js_methods(app::T)::String where {T<:ReactiveModel}
""
end
js_methods(::DataType) = ""
js_methods(::T) where T = js_methods(T)

# deprecated, now part of the model
function js_methods_events()::String
Expand All @@ -51,7 +50,7 @@ function js_methods_events()::String
end

"""
function js_computed(app::T) where {T<:ReactiveModel}
function js_computed(::Type{<:T}) where {T<:ReactiveModel}

Defines js functions for the `computed` section of the vue element.
These properties are updated every time on of the inner parameters changes its value.
Expand All @@ -72,14 +71,13 @@ js_computed(app::MyDashboard) = \"\"\"
\"\"\"
```
"""
function js_computed(app::T)::String where {T<:ReactiveModel}
""
end
js_computed(::DataType) = ""
js_computed(::T) where T = js_computed(T)

const jscomputed = js_computed

"""
function js_watch(app::T) where {T<:ReactiveModel}
function js_watch(::Type{<:T}) where {T<:ReactiveModel}

Defines js functions for the `watch` section of the vue element.
These functions are called every time the respective property changes.
Expand All @@ -95,7 +93,7 @@ Expected result types of the function are
Updates the `fullName` every time `firstName` or `lastName` changes.

```julia
js_watch(app::MyDashboard) = \"\"\"
js_watch(::Type{<:MyDashboard}) = \"\"\"
firstName: function (val) {
this.fullName = val + ' ' + this.lastName
},
Expand All @@ -105,9 +103,8 @@ js_watch(app::MyDashboard) = \"\"\"
\"\"\"
```
"""
function js_watch(m::T)::String where {T<:ReactiveModel}
""
end
js_watch(::DataType) = ""
js_watch(::T) where T = js_watch(T)

const jswatch = js_watch

Expand All @@ -125,7 +122,7 @@ const jstemplate = js_template


"""
function client_data(app::T)::String where {T<:ReactiveModel}
function client_data(::Type{<:MyApp})::String

Defines additional data that will only be visible by the browser.

Expand All @@ -135,13 +132,21 @@ In order to use the data you most probably also want to define [`js_methods`](@r

```julia
import Stipple.client_data
client_data(m::Example) = client_data(client_name = js"null", client_age = js"null", accept = false)
client_data(::Type{<:Example}) = client_data(client_name = js"null", client_age = js"null", accept = false)
```
will define the additional fields `client_name`, `client_age` and `accept` for models of type `Example`.
These definitions should, of course, not overlap with existing fields of your model.
### Note
Previously we defined the client_data function differently. This will continue to work,
but the new way might have some advantages in the future for mixins. Here is the old way:
```julia
client_data(::Example) = client_data(client_name = js"null", client_age = js"null", accept = false)
```
will define the additional fields `client_name`, `client_age` and `accept` for the model `Example`. These should, of course, not overlap with existing fields of your model.
"""
client_data(app::T) where T <: ReactiveModel = Dict{String, Any}()
client_data(::Type{<:ReactiveModel}) = Dict{String, Any}()
client_data(::T) where T = client_data(T)

client_data(;kwargs...) = Dict{String, Any}([String(k) => v for (k, v) in kwargs]...)
client_data(; kwargs...) = Dict{String, Any}([String(k) => v for (k, v) in kwargs]...)

for (f, field) in (
(:js_before_create, :beforeCreate), (:js_created, :created), (:js_before_mount, :beforeMount), (:js_mounted, :mounted),
Expand All @@ -151,7 +156,7 @@ for (f, field) in (
field_str = string(field)
Core.eval(@__MODULE__, quote
"""
function $($f)(app::T)::Union{Function, String, Vector} where {T<:ReactiveModel}
function $($f)(::Type{<:T})::Union{Function, String, Vector} where {T<:ReactiveModel}

Defines js statements for the `$($field_str)` section of the vue element.

Expand All @@ -163,7 +168,7 @@ for (f, field) in (
### Example 1

```julia
$($f)(app::MyDashboard) = \"\"\"
$($f)(::Type{<:MyDashboard}) = \"\"\"
if (this.cameraon) { startcamera() }
\"\"\"
```
Expand All @@ -174,17 +179,22 @@ for (f, field) in (
startcamera() = "if (this.cameraon) { startcamera() }"
stopcamera() = "if (this.cameraon) { stopcamera() }"

$($f)(app::MyDashboard) = [startcamera, stopcamera]
$($f)(::Type{<:MyDashboard}) = [startcamera, stopcamera]
```
Checking the result can be done in the following way
```
julia> render(MyApp())[:$($field_str)]
JSONText("function(){\n if (this.cameraon) { startcamera() }\n\n if (this.cameraon) { stopcamera() }\n}")
```
### Note
Previously we defined the function differently. This will continue to work,
but the new way might have some advantages in the future for mixins. Here is the old way:
```julia
$($f)(::MyDashboard) = [startcamera, stopcamera]
```
"""
function $f(app::T)::String where {T<:ReactiveModel}
""
end
$f(::DataType)::String = ""
$f(::T) where T = $f(T)
end)
end

Expand Down Expand Up @@ -266,13 +276,11 @@ function js_initscript(initscript::String)
"""
end

function js_created_auto(x)
""
end
js_created_auto(::DataType) = ""
js_created_auto(::T) where T = js_created_auto(T)

function js_watch_auto(x)
""
end
js_watch_auto(::DataType) = ""
js_watch_auto(::T) where T = js_watch_auto(T)

# methods to be used directly as arguments to js_methods

Expand Down
Loading
Loading