Skip to content

Merge dev with first release candidate to master #56

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Closed
wants to merge 151 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
151 commits
Select commit Hold shift + click to select a range
e2cbeaf
in work
waralex Apr 24, 2020
4b54091
Merge branch 'dash_arguments_refactor' into generated_components
waralex Apr 24, 2020
835d494
:tada: add gzip compression support
Apr 25, 2020
ddf58ae
application resources
waralex Apr 26, 2020
4624641
application resources
waralex Apr 26, 2020
e2e9d7f
Merge branch 'dev' into generated_components
waralex Apr 26, 2020
3ae4aa4
add compress argument
Apr 26, 2020
f79f038
create test env & add deps
Apr 27, 2020
ee7b556
:rotating_light: add unit tests for gzip
Apr 27, 2020
55471ab
:sparkles: add config.yml
Apr 27, 2020
832a717
add false to process_assets tests
Apr 27, 2020
b0bf83a
:see_no_evil: roll new code into try/catch
Apr 27, 2020
08bb621
use !isnothing(body)
Apr 27, 2020
cd5c520
Merge pull request #14 from plotly/14-add-compression
waralex Apr 27, 2020
b623848
Merge branch 'dev' into generated_components
waralex Apr 27, 2020
5b92333
Router etc
waralex May 3, 2020
11b14cf
almost ready to pr
waralex May 3, 2020
85b1acd
fix external urls
waralex May 4, 2020
b8773ec
app refactoring
waralex May 4, 2020
f7f1083
fix
waralex May 4, 2020
76901cd
fixes
waralex May 4, 2020
d7c764c
replace name with root_path
waralex May 5, 2020
272b99f
try to use plotly image
May 10, 2020
9a4c853
restore julia:latest
May 10, 2020
c571495
:sparkles: add Julia integration test
May 10, 2020
bd8e893
add startup message
May 12, 2020
f431975
Merge pull request #21 from plotly/enable-integration
rpkyle May 12, 2020
48152c0
try to pull from current branch
May 12, 2020
67d2625
add undo/redo test
May 13, 2020
dcb6c90
try to speed up compilation
May 13, 2020
7822674
increase timeout
May 13, 2020
da34ced
remove name arg, base hot restart
waralex May 15, 2020
c5fee8d
basic callbacks tests
waralex May 16, 2020
d4467e7
integration tests
waralex May 17, 2020
9d94c51
remove changed props
waralex May 17, 2020
3eca5d3
remove components jsons
waralex May 17, 2020
41f1b26
test fix
waralex May 17, 2020
c763d0b
Merge branch 'generated_components' into hot_reload
waralex May 17, 2020
bcbffb3
assets and callbacks test
waralex May 17, 2020
8dd2dd3
:rotating_light: add test for meta tags
May 18, 2020
50d7afa
switch off debug mode
May 18, 2020
99ba811
:pencil2: s/childs/children/g
May 18, 2020
782ac3c
:necktie: add CRLF at EOF
May 18, 2020
61bc449
Update src/app/callbacks.jl
rpkyle May 18, 2020
4794a5b
Update src/app/dashapp.jl
rpkyle May 18, 2020
5f02cbe
Update src/app/dashapp.jl
rpkyle May 18, 2020
b4151c8
Update src/app/dashapp.jl
rpkyle May 18, 2020
ae4afaf
Update src/app/dashapp.jl
rpkyle May 18, 2020
705666c
Update src/app/dashapp.jl
rpkyle May 18, 2020
89f48e6
Update src/app/dashapp.jl
rpkyle May 18, 2020
ac865d6
Update src/app/dashapp.jl
rpkyle May 18, 2020
7c3c5bb
Update src/app/dashapp.jl
rpkyle May 18, 2020
bd0588c
s/segmets_vector/segments_vector/g
May 18, 2020
6d03c77
Update src/handler/handlers.jl
rpkyle May 18, 2020
014e8e9
add missing env vars
May 18, 2020
ffb3520
Merge branch 'generated_components' of github.com:plotly/Dash.jl into…
May 18, 2020
97cce28
modify help header, match Dash for :snake:
May 18, 2020
133e3dc
Update src/app/callbacks.jl
waralex May 18, 2020
24b44a9
Merge branch 'generated_components' into hot_reload
waralex May 18, 2020
248f3a7
try parallelizing
May 18, 2020
675164d
Merge branch 'generated_components' of github.com:plotly/Dash.jl into…
May 18, 2020
1eb86fa
try pytest-xdist
May 18, 2020
4b229be
set parallelism
May 18, 2020
a8d89de
:hocho: parallelism, slower
May 18, 2020
0fe297c
Merge pull request #18 from plotly/generated_components
waralex May 18, 2020
c5b68fc
in process
waralex May 18, 2020
74fd13e
Merge branch 'dev' into hot_reload
waralex May 18, 2020
1e4412b
use dev, not add-julia-runner
rpkyle May 19, 2020
04f56d4
hot reload works
waralex May 19, 2020
971d89e
close subprocess on exit + tests
waralex May 19, 2020
e856af7
fixes
waralex May 19, 2020
fdf9e12
change dash branch
waralex May 19, 2020
02fb9de
fix issue with missing children prop
waralex May 20, 2020
0f6ef2c
fix headers
waralex May 20, 2020
31847e2
Merge pull request #28 from plotly/fix_missing_children
waralex May 20, 2020
dddb875
Update src/Dash.jl
waralex May 21, 2020
556f838
another way of restart
waralex May 21, 2020
8432617
little fix + increase timeouts
waralex May 21, 2020
e3f4194
fix
waralex May 21, 2020
d034466
Create CHANGELOG.md
rpkyle May 21, 2020
7d7faae
clientside callbacks
waralex May 22, 2020
14e8168
Update src/Dash.jl
waralex May 22, 2020
262cbba
:pencil2: s/reaload/reload/g
May 22, 2020
1aac87b
Merge branch 'hot_reload' of github.com:plotly/Dash.jl into hot_reload
May 22, 2020
f297b27
Create CHANGELOG.md
rpkyle May 21, 2020
e71add4
improve message
May 22, 2020
e169159
changelog
waralex May 22, 2020
921e3e4
changelog
waralex May 22, 2020
f8ce6c6
Merge branch 'dev' into hot_reload
rpkyle May 22, 2020
4b8636d
disable Labeler within GitHub Workflows
May 22, 2020
27a2607
Merge branch 'hot_reload' of github.com:plotly/Dash.jl into hot_reload
May 22, 2020
ff2adcc
restore labeler
May 22, 2020
b50e5dc
Merge pull request #25 from plotly/hot_reload
waralex May 22, 2020
8a43c89
Update CHANGELOG.md links
rpkyle May 22, 2020
7a9c14c
Update CHANGELOG.md links
rpkyle May 22, 2020
73b3aef
add :books: documentation for dev tools features
May 22, 2020
92fd3e3
clean up formatting
May 22, 2020
59657b6
Update README.md
rpkyle May 22, 2020
d3be0f2
Merge branch 'dev' into clientside_callbacks
waralex May 22, 2020
eb54990
minor fix
waralex May 22, 2020
34411bb
Delete geckodriver.log
rpkyle May 23, 2020
199f051
Update README.md
rpkyle May 23, 2020
645d218
Create .gitattributes
rpkyle May 23, 2020
9d2d74f
Merge pull request #30 from plotly/clientside_callbacks
waralex May 26, 2020
f376132
callback! refactoring
waralex May 29, 2020
5a81d6f
Fixed examples
PallHaraldsson Jun 4, 2020
b8249e2
Fixed another example
PallHaraldsson Jun 4, 2020
b302856
Merge pull request #40 from PallHaraldsson/patch-1
waralex Jun 5, 2020
ff03b90
Merge branch 'dev' into callbacks_refactoring
waralex Jun 6, 2020
7c36096
flat callbacks
waralex Jun 7, 2020
308cee3
Merge pull request #39 from plotly/callbacks_refactoring
waralex Jun 8, 2020
f2e01c7
Fix spelling
jbampton Jul 4, 2020
fc8197f
Merge pull request #43 from jbampton/fix-spelling
alexcjohnson Jul 6, 2020
a5070b8
Add a GitHub action to lint the Markdown.
jbampton Jul 6, 2020
9e4ae6e
callback_context
waralex Jul 13, 2020
68bec5f
Merge pull request #44 from jbampton/lint-markdown
waralex Jul 13, 2020
4a3f7f1
Merge branch 'dev' into callback_context
waralex Jul 13, 2020
a14eb5d
callback_context
waralex Jul 13, 2020
b723242
callback_context
waralex Jul 13, 2020
8399bc1
fix
waralex Jul 13, 2020
b527a48
increase test timeouts
waralex Jul 13, 2020
7728f5f
ci_changes
waralex Jul 13, 2020
94313a7
ci_changes
waralex Jul 13, 2020
eb51d4b
fixes
waralex Jul 14, 2020
9acf95f
Merge pull request #46 from plotly/callback_context
waralex Jul 14, 2020
441722a
pattern match
waralex Jul 15, 2020
9d8ec2a
fix
waralex Jul 15, 2020
5ddb02c
increase timeout in wildcard tests
waralex Jul 15, 2020
0524f46
Merge pull request #47 from plotly/pattern_match
waralex Jul 16, 2020
8a1d1d1
front end debug
waralex Aug 5, 2020
41cfbd0
degug exceptions
waralex Aug 6, 2020
e52c770
Update src/HttpHelpers/handlers.jl
waralex Aug 7, 2020
45cb667
fixes
waralex Aug 12, 2020
b059ddd
Merge branch 'debugging_logging' of https://github.com/plotly/Dash.jl…
waralex Aug 12, 2020
76af75b
fix
waralex Aug 12, 2020
cc3ebfe
Merge pull request #51 from plotly/debugging_logging
waralex Aug 12, 2020
313d18d
Fix typo in README.md
amanbh Aug 15, 2020
8e6b087
Merge pull request #52 from amanbh/patch-1
alexcjohnson Aug 17, 2020
e0a749b
fix typo
waralex Aug 21, 2020
dc4deb1
reverse dependency
waralex Aug 23, 2020
c976cb6
ci+readme changes
waralex Aug 24, 2020
c5fd554
compat
waralex Aug 24, 2020
d7f0e2e
add DashBase to ci and readme
waralex Aug 24, 2020
767637e
increase timeout
waralex Aug 24, 2020
93a2f49
increase test timeouts
waralex Aug 24, 2020
e01ee49
Update src/Front.jl
waralex Aug 26, 2020
1cfaf4a
change components repos to plotly
waralex Aug 27, 2020
9c6a26b
Merge branch 'first_release_candidat' of https://github.com/plotly/Da…
waralex Aug 27, 2020
150be4a
Update README.md
rpkyle Aug 27, 2020
b031aa7
Merge branch 'dev' into first_release_candidat
waralex Aug 28, 2020
c3d6a17
Merge pull request #54 from plotly/first_release_candidat
waralex Aug 28, 2020
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
58 changes: 58 additions & 0 deletions .circleci/config.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
version: 2

jobs:

test:
working_directory: ~/dashjl
docker:
- image: plotly/julia:ci
environment:
PERCY_PARALLEL_TOTAL: '-1'
PUPPETEER_SKIP_CHROMIUM_DOWNLOAD: 'True'

steps:
- checkout

- run:
name: ℹ️ CI Context
command: |
echo "TRIGGERER: ${CIRCLE_USERNAME}"
echo "BUILD_NUMBER: ${CIRCLE_BUILD_NUM}"
echo "BUILD_URL: ${CIRCLE_BUILD_URL}"
echo "BRANCH: ${CIRCLE_BRANCH}"
echo "RUNNING JOB: ${CIRCLE_JOB}"
echo "JOB PARALLELISM: ${CIRCLE_NODE_TOTAL}"
echo "CIRCLE_REPOSITORY_URL: ${CIRCLE_REPOSITORY_URL}"
echo $CIRCLE_JOB > circlejob.txt

- run:
name: 🔎 Unit tests
command: |
julia test/ci_prepare.jl

- run:
name: ⚙️ Integration tests
command: |
python -m venv venv
. venv/bin/activate
git clone --depth 1 https://github.com/plotly/dash.git -b dev dash-main
cd dash-main && pip install -e .[dev,testing] --progress-bar off && cd ~/dashjl
export PATH=$PATH:/home/circleci/.local/bin/
pytest --headless --nopercyfinalize --junitxml=test-reports/dashjl.xml --percy-assets=test/assets/ test/integration/
- store_artifacts:
path: test-reports
- store_test_results:
path: test-reports
- store_artifacts:
path: /tmp/dash_artifacts

- run:
name: 🦔 percy finalize
command: npx percy finalize --all
when: always

workflows:
version: 2
build:
jobs:
- "test"
1 change: 1 addition & 0 deletions .gitattributes
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
resources/* linguist-vendored
15 changes: 15 additions & 0 deletions .github/workflows/lint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
name: Lint Markdown

on: [push, pull_request]

jobs:
test:
runs-on: ubuntu-18.04
steps:
- uses: actions/checkout@v2
- name: Use Node.js
uses: actions/setup-node@v1
with:
node-version: '12.x'
- run: npm install -g [email protected]
- run: markdownlint '**/*.md' --ignore node_modules
5 changes: 4 additions & 1 deletion .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -8,4 +8,7 @@ components/*
lib/*
Manifest.toml
.DS_Store
docs/build
docs/build
venv
*.pyc
tmp
14 changes: 14 additions & 0 deletions .markdownlint.yml
Original file line number Diff line number Diff line change
@@ -0,0 +1,14 @@
# MD001 Header levels should only increment by one level at a time
MD001: false

# MD013 Line length
MD013: false

# MD022 Headers should be surrounded by blank lines
MD022: false

# MD026 Trailing punctuation in header
MD026: false

# MD032 Lists should be surrounded by blank lines
MD032: false
30 changes: 30 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
# Change Log for Dash for Julia
All notable changes to this project will be documented in this file. This project adheres to Semantic Versioning.

## [UNRELEASED]
### Added
- Support for client side callbacks [#30](https://github.com/plotly/Dash.jl/pull/30)
- Support for hot reloading on application or asset changes [#25](https://github.com/plotly/Dash.jl/pull/25)
- Asset serving of CSS, JavaScript, and other resources [#18](https://github.com/plotly/Dash.jl/pull/18)
- Support for passing functions as layouts [#18](https://github.com/plotly/Dash.jl/pull/18)
- Resource registry for component assets [#18](https://github.com/plotly/Dash.jl/pull/18)
- Asynchronous component loading & fingerprinting component assets [#18](https://github.com/plotly/Dash.jl/pull/18)
- Developer tools UI support [#18](https://github.com/plotly/Dash.jl/pull/18)
- Dash environment variables are now supported [#18](https://github.com/plotly/Dash.jl/pull/18)
- Index page/layout validation now performed [#18](https://github.com/plotly/Dash.jl/pull/18)
- Support for `gzip` compression [#14](https://github.com/plotly/Dash.jl/pull/14)
- Parity with core Dash API parameters [#12](https://github.com/plotly/Dash.jl/pull/12)
- Integration tests are now supported, server startup message appears on app initialization [#21](https://github.com/plotly/Dash.jl/pull/21)

### Changed
- Dash.jl now starts via `run_server` with `host` and `port` arguments [#2](https://github.com/plotly/Dash.jl/issues/2)
- Defining layouts in Dash.jl now occurs similarly to Dash for Python/R [#1](https://github.com/plotly/Dash.jl/issues/1)

### Removed
- `make_handler` no longer used to start Dash server [#2](https://github.com/plotly/Dash.jl/issues/2)
- `layout_maker` has been removed [#18](https://github.com/plotly/Dash.jl/pull/18)
- `layout_maker` is no longer called by the app developer to define the layout [#1](https://github.com/plotly/Dash.jl/issues/1)

### Fixed
- Request headers are now properly specified [#28](https://github.com/plotly/Dash.jl/issues/28)
- Unspecified `children` now passed as `nothing` rather than undefined [#27](https://github.com/plotly/Dash.jl/issues/27)
18 changes: 15 additions & 3 deletions Project.toml
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,35 @@ authors = ["Alexandr Romanenko"]
version = "0.1.0"

[deps]
CodecZlib = "944b1d66-785c-5afd-91f1-9de20f533193"
DashBase = "03207cf0-e2b3-4b91-9ca8-690cf0fb507e"
DashCoreComponents = "1b08a953-4be3-4667-9a23-9da06441d987"
DashHtmlComponents = "1b08a953-4be3-4667-9a23-24100242a84a"
DashTable = "1b08a953-4be3-4667-9a23-f0e2ba4deb9a"
DataStructures = "864edb3b-99cc-5e75-8d2d-829cb0a9cfe8"
HTTP = "cd3eb016-35fb-5094-929b-558a96fad6f3"
JSON = "682c06a0-de6a-54ab-a142-c8b1cf79cde6"
JSON2 = "2535ab7d-5cd8-5a07-80ac-9b1792aadce3"
LibGit2 = "76f85450-5226-5b5a-8eaa-529ad045b433"
MD5 = "6ac74813-4b46-53a4-afec-0b5dc9d7885c"
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
PlotlyBase = "a03496cd-edff-5a9b-9e67-9cda94a718b5"
Sockets = "6462fe0b-24de-5631-8697-dd941f90decc"
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
UUIDs = "cf7118a7-6976-5b1a-9a39-7adc72f591a4"

[compat]
julia = "1.1"
CodecZlib = "0.7.0"
DashBase = "0.1.0"
DashCoreComponents = "1.10.2"
DashHtmlComponents = "1.0.3"
DashTable = "4.9.0"
DataStructures = "0.17.5"
HTTP = "0.8.6"
HTTP = "0.8.10"
JSON = "0.21.0"
JSON2 = "0.3.1"
MacroTools = "0.5.1"
PlotlyBase = "0.3.0"
julia = "1.1"

[extras]
Test = "8dfed614-e22c-5e08-85e1-65c5234f0b40"
Expand Down
113 changes: 74 additions & 39 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
## Dash for Julia
# Dash for Julia

#### Create beautiful, analytic applications in Julia.

Expand All @@ -8,11 +8,23 @@ Built on top of Plotly.js, React and HTTP.jl, [Dash](https://plotly.com/dash/) t

## Installation

Julia version >= 1.2 is required.
It also works in 1.1 now, but I do not plan testing and support for versions under 1.2
Please ensure that you are using a version of Julia >= 1.2.

To install the most recently released version:

```julia
using Pkg; Pkg.add(PackageSpec(url="https://github.com/plotly/Dash.jl.git"))
```

To install the latest (stable) development version instead:

```julia
import Pkg; Pkg.add(Pkg.PackageSpec(url = "https://github.com/plotly/Dash.jl.git"))
using Pkg
Pkg.add(PackageSpec(url="https://github.com/plotly/DashBase.jl.git"))
Pkg.add(PackageSpec(url="https://github.com/plotly/dash-html-components.git", rev="master"))
Pkg.add(PackageSpec(url="https://github.com/plotly/dash-core-components.git", rev="master"))
Pkg.add(PackageSpec(url="https://github.com/plotly/dash-table.git", rev="master"))
Pkg.add(PackageSpec(url="https://github.com/plotly/Dash.jl.git", rev="dev"))
```

## Usage
Expand All @@ -21,8 +33,11 @@ import Pkg; Pkg.add(Pkg.PackageSpec(url = "https://github.com/plotly/Dash.jl.git

```jldoctest
julia> using Dash
julia> app = dash("Test app", external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])

julia> using DashHtmlComponents
julia> using DashCoreComponents

julia> app = dash(external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])

julia> app.layout = html_div() do
html_h1("Hello Dash"),
html_div("Dash.jl: Julia interface for Dash"),
Expand All @@ -37,71 +52,79 @@ julia> app.layout = html_div() do
)
)
end

julia> run_server(app, "0.0.0.0", 8080)
```
* The `DashApp` struct represent dashboard application.
* To make `DashApp` struct use `dash(layout_maker::Function, name::String; external_stylesheets::Vector{String} = Vector{String}(), url_base_pathname="/", assets_folder::String = "assets")`` where `layout_maker` is a function with signature ()::Component
* Unlike the python version where each Dash component is represented as a separate class, all components in Dash.jl are represented by struct `Component`.
* You can create `Component` specific for concrete Dash component by the set of functions in the form ``lowercase(<component package>)_lowercase(<component name>)``. For example, in python html `<div>` element is represented as `HTML.Div` in Dasboards it is created using function `html_div`
* The list of all supported components is available in docstring for Dasboards module
* All functions for a component creation have the signature `(;kwargs...)::Component`. List of key arguments specific for the concrete component is available in the docstring for each function
* Functions for creation components which have `children` property have two additional methods ``(children::Any; kwargs...)::Component`` and ``(children_maker::Function; kwargs..)::Component``. `children` must by string or number or single component or collection of components
* ``make_handler(app::Dash; debug::Bool = false)`` makes handler function for using in HTTP package

* The `DashApp` struct represents a dashboard application.
* To make `DashApp` struct use `dash(layout_maker::Function, name::String; external_stylesheets::Vector{String} = Vector{String}(), url_base_pathname="/", assets_folder::String = "assets")` where `layout_maker` is a function with signature ()::Component
* Unlike the Python version where each Dash component is represented as a separate class, all components in Dash.jl are represented by struct `Component`.
* You can create `Component` specific for concrete Dash component by the set of functions in the form ``lowercase(<component package>)_lowercase(<component name>)``. For example, in Python html `<div>` element is represented as `HTML.Div` in Dashboards it is created using function `html_div`
* The list of all supported components is available in docstring for Dashboards module.
* All functions for a component creation have the signature `(;kwargs...)::Component`. List of key arguments specific for the concrete component is available in the docstring for each function.
* Functions for creation components which have `children` property have two additional methods ``(children::Any; kwargs...)::Component`` and ``(children_maker::Function; kwargs..)::Component``. `children` must by string or number or single component or collection of components.
* ``make_handler(app::Dash; debug::Bool = false)`` makes a handler function for using in HTTP package.

__Once you have run the code to create the Dashboard, go to `http://127.0.0.1:8080` in your browser to view the Dashboard!__

### Basic Callback

```jldoctest

julia> using Dash
julia> app = dash("Test app", external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])
julia> using DashHtmlComponents
julia> using DashCoreComponents

julia> app = dash(external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])

julia> app.layout = html_div() do
dcc_input(id = "my-id", value="initial value", type = "text"),
html_div(id = "my-div")
html_div(id = "my-div")
end

julia> callback!(app, callid"my-id.value => my-div.children") do input_value
julia> callback!(app, Output("my-div", "children"), Input("my-id", "value")) do input_value
"You've entered $(input_value)"
end
julia> run_server(app, "0.0.0.0", 8080)

julia> run_server(app, "0.0.0.0", 8080)
```
* You can make your dashboard interactive by register callbacks for changes in frontend with function ``callback!(func::Function, app::Dash, id::CallbackId)``
* Inputs and outputs (and states, see below) of callback are described by struct `CallbackId` which can easily created by string macro `callid""`
* `callid""` parse string in form ``"[{state1 [,...]}] input1[,...] => output1[,...]"`` where all items is ``"<element id>.<property name>"``
* Callback function must have the signature(states..., inputs...) and return data for output

* You can make your dashboard interactive by register callbacks for changes in frontend with function ``callback!(func::Function, app::Dash, output, input, state)``
* Inputs and outputs (and states, see below) of callback can be `Input`, `Output`, `State` objects or vectors of this objects
* Callback function must have the signature(inputs..., states...), and provide a return value comparable (in terms of number of elements) to the outputs being updated.

### States and Multiple Outputs

```jldoctest
julia> using Dash
julia> app = dash("Test app", external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])

julia> using DashHtmlComponents
julia> using DashCoreComponents

julia> app = dash(external_stylesheets = ["https://codepen.io/chriddyp/pen/bWLwgP.css"])

julia> app.layout = html_div() do
dcc_input(id = "my-id", value="initial value", type = "text"),
html_div(id = "my-div"),
html_div(id = "my-div2")
html_div(id = "my-div2")
end

julia> callback!(app, callid"{my-id.type} my-id.value => my-div.children, my-div2.children") do state_value, input_value
julia> callback!(app, [Output("my-div","children"), Output("my-div2","children")], Input("my-id", "value"), State("my-id", "type")) do input_value, state_value
"You've entered $(input_value) in input with type $(state_value)",
"You've entered $(input_value)"
end
julia> run_server(app, "0.0.0.0", 8080)
```
* For multiple output callback must return any collection with element for each output

## Comparation with original python syntax
## Comparison with original Python syntax

### component naming:

`html.Div` => `html_div`, `dcc.Graph` => `dcc_graph` and etc

### component creation:

Just like in Python, functions for creating components have keywords arguments, which are the same as in Python. ``html_div(id="my-id", children="Simple text")``.
For components that have `children` prop, two additional signatures are available. ``(children; kwargs..)`` and ``(children_maker::Function; kwargs...)`` so You can write ``html_div("Simple text", id="my-id")`` for simple elements or avoid the hell of nested brackets with `do` syntax for complex elements:
Just as in Python, functions for declaring components have keyword arguments, which are the same as in Python. ``html_div(id="my-id", children="Simple text")``.
For components which declare `children`, two additional signatures are available. ``(children; kwargs..)`` and ``(children_maker::Function; kwargs...)`` so one can write ``html_div("Simple text", id="my-id")`` for simple elements, or choose an abbreviated syntax with `do` syntax for complex elements:

```julia
html_div(id="outer-div") do
Expand All @@ -111,25 +134,30 @@ html_div(id="outer-div") do
end
end
```

### application and layout:

* python:

```python
app = dash.Dash("Test", external_stylesheets=external_stylesheets)
app.layout = html.Div(children=[....])
```

* Dash.jl:

```julia
app = dash("Test", external_stylesheets=external_stylesheets)
app = dash("Test", external_stylesheets=external_stylesheets)

app.layout = html_div() do
......
end

```

### callbacks:
* python:

* Python:

```python
@app.callback(Output('output', 'children'),
[Input('submit-button', 'n_clicks')],
Expand All @@ -139,15 +167,22 @@ def update_output(n_clicks, state1, state2):
.....

```

* Dash.jl:

```julia
callback!(app, callid"""{state1.value, state2.value}
submit-button.n_clicks
=> output.children""" ) do state1, state2, n_clicks
callback!(app, Output("output", "children"),
[Input("submit-button", "n_clicks")],
[State("state-1", "value"),
State("state-2", "value")]) do n_clicks, state1, state2
.....
end
```
Be careful - in Dash.jl states came first in arguments list

### json:
I use JSON2 for json serialization/deserialization, so in callbacks all json objects are NamedTuples not Dicts. In component props you can use both Dicts and NamedTuples for json objects. But be careful with single property objects: `layout = (title = "Test graph")` is not interpreted as NamedTuple by Julia - you need add comma at the end `layout = (title = "Test graph",)`
Be careful - in Dash.jl states come first in an arguments list.

### JSON:

I use JSON2.jl for JSON serialization/deserialization, so in callbacks all JSON objects are `NamedTuples` rather than dictionaries. Within component properties you can use both `Dict` and `NamedTuple` for JSON objects.

Note when declaring elements with a single properly that `layout = (title = "Test graph")` is not interpreted as a `NamedTuple` by Julia - you'll need to add a comma when declaring the layout, e.g. `layout = (title = "Test graph",)`
Loading