<commit_before>= Untangled Client Docs
:source-highlighter: coderay
:source-language: clojure
:toc:
:toc-placement!:
:toclevels: 3
:sectlinks:
:sectanchors:
:sectnums:

ifdef::env-github[]
:tip-caption: :bulb:
:note-caption: :information_source:
:important-caption: :heavy_exclamation_mark:
:caution-caption: :fire:
:warning-caption: :warning:
endif::[]

ifdef::env-github[]
toc::[]
endif::[]

== Basic UI

Untangled uses Om, which in turn uses https://facebook.github.io/react/index.html[React^] underneath.

=== Creating a Custom React Class

The mechanism for creating components is the `defui` macro:

[source]
----
(defui ComponentClassName
  Object
  (componentWillUpdate [this nextprops nextstate] (println "Component will update"))
  (render [this]
    (dom/div nil "Hello world")))
----

This macro generates a React class as a plain JavaScript class, so it is completely compatible with the
React ecosystem.

Notice the use of `Object`. It indicates that the following method bodies (like in
http://clojure.org/reference/protocols[protocols^]) are being added to the
generated class. From an OO perspective, this is like saying \"my widget extends Object\". The `render`
method is the only method you need, but you can also add in your own methods or React lifecycle
methods.

=== React lifecycle methods

If you wish to provide
https://facebook.github.io/react/docs/component-specs.html#lifecycle-methods[lifecycle methods^], you can
define them under the Object section of the UI:

[source]
----
(defui WidgetWithHook
  Object
  (componentWillUpdate [this nextprops nextstate] (println "Component will update"))
  (render [this]
    (dom/div nil "Hello world")))
----

==== Lifecycle method signatures

For reference these are the signatures you should use for the React Lifecycle methods:

[source]
----
(initLocalState [this])
(componentWillReceiveProps [this next-props])
(componentWillUpdate [this next-props next-state])
(componentDidUpdate [this prev-props prev-state])
(componentWillMount [this])
(componentDidMount [this])
(componentWillUnmount [this])
----

=== ClojureScript and React – HTML differences

Here are some common things you'll want to know how to do that are different when rendering with Om/ClojureScript:

- Inline styles are specified with real maps `(dom/p #js { :style #js {:backgroundColor \"rgb(120,33,41)\"} } ...)`.
Note the nested use of raw Javascript maps. These are passed directly to React. Using cljs persistent data structures
won't work.
- CSS class names are specified with `:className` instead of `:class`.
- Any time there are adjacent elements of the same type in the DOM, they should each have a unique `:key`
attribute. This is typically generated by a function you supply to the Om factory function, but you can
also do it manually.

=== Element factory

In order to render components on the screen you need an element factory.
You generate a factory with `om/factory`, which will then
act like a new 'tag' for your DOM. We commonly prefix these factories with `ui-` so
we don't confuse them with query attribute names and other local bindings. If the
component is ever to be rendered in a list of adjacent elements then the factory should
be given a key function for generating unique React keys on the component.

[source]
----
(def ui-widget (om/factory Widget {:keyfn (fn [props] (get props :some-prop))}))
----

=== Rendering a Component, Sending, and Accessing Properties

You can now render a widget inside of any other component using `(ui-widget { :prop 1 })`.

You access properties in a component using `om/props`:"

[source]
----
(defui Widget
  Object
  (render [this]
    (let [{:keys [name]} (om/props this)]
      (dom/div nil (str "Hello " name)))))

(def ui-widget (om/factory Widget))

...
   (ui-widget {:name "Sally"})
----

=== Computed data like Callbacks

In plain React you store component local state and pass data from the parent to the child through props.
You also pass your callbacks through props. In Untangled, we need a slight variation of
this because a component can have a query that asks the underlying system for data.

If you complect callbacks and such with this queried data then you run into trouble because the rendering system
can re-render a component without going through the parent, meaning that callbacks could be lost.

So, in general *props are for passing data that the component requested from a query*.

As such, Om has an additional mechanism for passing things that were not specifically asked for in a query: Computed
properties.

For your Om UI to function properly you must attach computed properties to props via the helper function `om/computed`.
The child can look for these computed properties using `om/get-computed`.

=== Stateful components

Earlier we stress that your components should be stateless whenever possible. There are a few
notable exceptions that we have found useful (or even necessary):

- The Untangled support viewer shows each app state change. User input (each letter they type) can
be quite tedious to watch in a support viewer. Moving these kinds of interstitial form interactions
into local component state causes little harm, and greatly enhances support. Om automatically hooks up local
state to input fields when you use "uncontrolled" form elements (which means you didn't set value/checked).
- External library integration. We use stateful components like D3 visualizations.

==== Form inputs

Om already hooks local state to form elements. So, in fact, you have to override this to *not* use
component local state. For text controls we'd recommend you leave it this way. For other controls like
checkboxes it is probably best to override this.

==== External library state

See the D3 example in the Untangled Tutorial.

=== Built-in React DOM

All of the standard HTML tags have pre-built React components, accessible from the `om.dom` namespace.

[source]
----
(ns ui
  (:require [om.dom :as dom]))

(defui Widget
  Object
  (render [this]
    (dom/div nil (str "Hello " name))))
----

== Application Database Format

Untangled applications use the default Om database format. This is a simple graph database format made from
standard Clojurescript persistent data structures: Maps and vectors. The entire database is a map.

=== Tables

Specific items in the database are stored in tables. Each table is indexed by a top-level key in the database.
Items in the database can refer to other items via a foreign reference, which is formatted as an Ident. It is also legal
to have top-level data that is not a table.

[source]
----
{:value 53
 :table/by-id { 1 { :id 1 :x 1 } } }
----

The only way to tell a table from a value is by convention. Tables will usually be named in a way that
indicates what the primary key of the table is (e.g. `by-id`), and will be maps of maps. Regular values can
be anything, including an Ident.

=== Idents

An Ident is nothing more than a two element vector, where the first entry is a keyword (the "name" of a database table)
and the second entry is the ID of the object in that table: `[:table-name id]`

In the database above you would describe the object in the table as `[:table/by-id 1]`.

=== Graph

Combining regular values, tables, and idents gives you the overall database format which can support any arbitrary
graph. The database below has a list of two people (via idents pointing to the people in the table), and each
person has a pointer to the person that is their mate. This creates a graph with a loop (when following mate).

[source]
----
{:my-list [ [:people/by-id 1] [:people/by-id 2] ]
 :people/by-id {
   1 { :db/id 1 :person/name "Tony" :person/mate [:people/by-id 2]}
   2 { :db/id 2 :person/name "Jill" :person/mate [:people/by-id 1]}}}
----

[ditaa,target=basic-db]
....
                                                  +-------------+
                                                  |             |
                                           Table  v             |
 +-------+      +-----------------+       +----------------+    |
 |my-list|----->| :people/by-id 1 |------>| 1  Tony    mate|-+  |
 +-------+      +-----------------+       |                | |  |
                | :people/by-id 2 |------>| 2  Jill    mate|-+--+
                +-----------------+       +----------------+ |
                                                 ^           |
                                                 |           |
                                                 +-----------+
....

== The Query Language

The query language is a subset of Datomic Pull syntax. It is a syntax that is designed to walk a graph and produce a
tree (which is suitable for a UI, which is naturally a tree).

Queries are written as a vector.

=== Attributes

The query `[:a :b :c]` means read the attributes `:a` `:b`, and `:c` from the current object. For example,
if this query was against the root of the graph, it would mean the top-level database itself should contain the
keys `:a`, `:b`, and `:c`. In the context of a join (or sequence of joins) it indicates attribute reads in that
context.

One may query any attribute that makes sense, including an entire table. For example, the query `[:people/by-id]`
against the database above will return:

[source]
----
{ :people/by-id { 1 { :db/id 1 :person/name "Tony" :person/mate [:people/by-id 2]}
                  2 { :db/id 2 :person/name "Jill" :person/mate [:people/by-id 1]}}}
----

=== Joins

Joins can be done against reference typed attributes (which essentially means an attribute holding an ident).

Joins are written as a map, where the key is the join point, and the value is a sub-query: `[{:my-list [:person/name]}]`. If
the join point is a vector of idents, then it is a to-many join and the query will result in multiple values. If
the join point is a single ident, then it is a to-one join, and the query will result in a single value. In the
context of our database above this query should return the names of the people in my list.

The join shown in the prior paragraph against our database above would result in:

[source]
----
{ :my-list [ {:person/name "Tony"} {:person/name "Jill"} ] }
----

=== Recursion

Queries can be recursive. In the case where the graph has a normal termination point (such as bullet lists) you
can use `...` to indicate a recursive join: `[{:list [:item/name {:sublist ...}]}]`

This would return a nested map that would follow the graph database links and possibly return something like this:

[source]
----
{ :list { :item/name "A"
          :sublist [ { :item/name "A.1" }
                     { :item/name "A.1" :sublist [ { :item/name "A.1.1" } ]}]}}
----

In our database from earlier, we have a loop. The query engine will automatically detect loops and stop, but you can manually
limit the recusion depth using a number instead of `...`: `[{:my-list [:person/name {:person/mate 1}]}]`
which would result in:

[source]
----
{ :my-list [ { :person/name "Tony" :person/mate { :person/name "Jill" } }
             { :person/name "Jill" :person/mate { :person/name "Tony" } } ]}
----

=== Unions

Union queries are used strictly as the subquery on joins, and are represented by a map. The keys of the map represent
the possible choices of subquery to run, and the value represents the subquery.

In the case of a union query one must realize that it is impossible to say what the query means until you look at the
actual database. Here is how they work:

. Examine the Ident at the join point of the join. Extract the keyword from that ident.
. Use the ident from (1) to look up the subquery from the union.
. Continue processing the query using that subquery

==== Union Example

Assume the following simple database:

[source]
----
{ :things [ [:people/by-id 1] [:animals/by-id 1] ]
  :people/by-id { 1 { :id 1 :type :person :name "Joe" } }
  :animals/by-id { 1 { :id 1 :type :dog :breed "Poodle" } } }
----

The following query: `[{:things { :people/by-id [:type :name]
                                  :animals/by-id [:type :breed] }}]`

would see the to-many join of `:things`, and for each element it would select the proper subquery. Resulting in:

[source]
----
[ { :type :person :name "Joe" }
  { :type :dog :breed "Poodle" } ]
----

Unions work fine on to-one joins exactly the same (returning only one result).

=== Query parameters

The query language includes support for adding a parameter map to every kind of query element. Untangled does not
support such parameters on the UI; however, since the same query language is used with respect to the server, it is
useful to know how to represent them.

Basically, you surround the query element with parens, and add a map as the second entry.

A property with a parameter: `[(:prop { :param 1})]`
A join with a parameter: `[({:prop [:a :b]} { :param 1})]`

Again, the the UI cannot make sense of these, but you can write such queries to the server and interpret them there.

== Initial Application State

Building your initial application state can be done in one of three ways. The recommended approach is to co-locate the
application state on the components that will use it. You may also hand-build either a tree (which can be
auto-normalized by the UI components into a graph). Finally, you may hand-build a graph database in the format described
earlier.

All three methods should result in a graph database. They are just different approaches at initial input, with different
pros/cons.

In all cases you must ensure that the components have Ident implementations that match up with your graph structure.

=== Using InitialAppState

This is probably the easiest method to code, and the easiest to keep straight during development because the data
is co-located with the queries and UI bits. The only disadvantage is that you cannot easily initialize parts of the
graph that do not have a UI representation (which is probably rare).

Implement the `InitialAppState` protocol on your ui components, and compose the initial state together just like you
do with queries:

[source]
----
(defui Child
  static uc/InitialAppState
  (initial-state [clz params] { :a 1 })
  ...)

(defui Parent
  static uc/InitialAppState
  (initial-state [clz params] { :x 1 :child (uc/initial-state Child) })
  ...)
----

Compose these all the way to your root component. Untangled will detect state on your root component, and use that
to construct the initial application database.

==== Unions and InitialAppState

To-one unions (e.g. used in tabbed interfaces) are automatically resolved if the branches of the union all define
InitialAppState implementations. The union component InitialAppState should define the "default" branch of the union.

=== Using a manually-constructed graph db

Simply create your database in a map, then *wrap it in an atom* and pass that via the `:initial-state` parameter of
`new-untangled-client`. This method is a bit of a hassle to maintain, but allows you to place things in the database
that are not (yet) in your UI.

=== Using a manually-constructed tree

Create a tree of data in a map. Pass it (not wrapped in an atom) to `:initial-state`. This technique is probably the
least useful. It is no more functional than the `InitialAppState` method, but is harder to maintain.

== Mutations

Untangled uses the abstract top-level transactions modelled by Om to evolve your application state. One should view
mutations as a function that evolves the state of the database:

[ditaa,target=mutations]
....
   /-----\                  /-----\
   | DB  |                  | DB' |
   |     |-----mutation---->|     |
   \-----/                  \-----/
....

Remember that almost everything in your database should be in a table. Mutations run in the context of components (or
can take parameters), which means that mutations can be given sufficient context (e.g. an ident of the thing to change)
to be fully abstract. An operation like `set-date-to-todate` might take the ident of a calendar widget. It need only
go to that place in the database and change the state there.

=== Built-in mutations

The following functions are built in (in `untangled.client.mutations`), and should generally only be used in the context of UI state changes (e.g.
folding, checkbox toggle, etc.). They invoke an internal transaction.

WARNING: You should not use these for bit-twiddling your real state! Define your own top-level abstract transactions.
These functions are really meant as convenience when dealing with controlled form inputs whose state is in your app
state.

- `(set-string! component field [event|value])`
- `(set-integer! field [event|value])`
- `(set-value! component field value)`
- `(toggle! component field)`

The first two take a value or event via a named parameter. For example `(m/set-string! this :name :event evt)` where
`evt` is a javascript input field event will extra the input's value and store it in the app db on the correct table
entry. These functions are really meant for working with form field state stored in the app database (as opposed to
component local state in uncontrolled form inputs).

=== Custom mutations

Untangled provides a multimethod that you can hook your own mutations into.

[source]
----
(ns app.mutations
  (:require [untangled.client.mutations :as m]))

(defmethod m/mutate 'my/mutation-symbol [env k params]
   { :action (fn[] ...) })
----

The three parameters are:

. `env`: The mutation environment. This is a map that contains:
-- `state`: The current app database atom. Use `swap!` to modify it
-- `ref`: The ident of the component that invoked the transaction
. `k`: This is the symbol, which is identical to the multimethod dispatch value (generally ignored)
. `params`: The parameters passed to the mutation

WARNING: The body should *not* side-effect! It should instead return a map. The map can contain:

- `:action`: A lambda function to run that will actually do the side-effects
- One or more remote indicators. Typically something like `:remote true`. See the section on remote mutations.

=== Invoking a mutation (`transact!`)

The `om/transact!` function is used to run a top-level transaction, and can invoke any number of mutations (in order).
It must be given a component reference or reconciler (typically the former) and a transaction to run. This looks just
like the query notation, but looks to include method calls (which will invoke the multimetod by symbol):

[source]
----
(om/transact! this '[(my/mutation-symbol {:x 1}) (other/mutations)])
----

The mutations in a transaction will run in order. Any of them that indicate a remote nature will be sent across the
wire to the server.

=== Post mutation hooks (experimental)

The is a multimethod for adding in post-mutation handlers that will run after the main mutation. These can be useful
when there is a common behavior that should happen after some set of mutations.

=== UI refresh after mutation

Untangled uses Om to manage the UI, and as such the UI refresh story is Om's story. The basic
rule is that when you `transact!`, the component (subtree) used for the transaction will be refreshed in the UI. This
allows you to automatically handle a lot of UI updates without having to think much; however, there are a couple of
general rules and tools you can use when this alone is insufficient.

. Move the transaction to a parent, and pass a callback that invokes (the parent's) transaction in the child. This
technique composes well (the parent has to know about the child, but the child need only support the abstract idea
of providing a callback hook). This is the most common technique in list management, where a child might have a delete
button, but the delete really needs to happen on the parent's list.
. Use follow-in reads

==== Follow-on Reads

The name "follow-on reads" is meant to describe the abstract way of refreshing the UI without thinking specifically
about the UI. A follow-on read is a way to indicate what (typically derived) data should be re-read from your
application database after a mutation. For example, if you have a friend list and you add someone to it, you might
need to re-read the count of friends for some indicator somewhere else on the screen. It is easy to reason about
the concept that the mutation `add-friend` affects the database value `:friend-count` (which you can explicitly store
as a denormalized value after each mutation, or derive in the UI by pulling in the list of friends and counting them).

Independent of how you store data in your database, you know what you've changed in a mutation. So, when you run
a mutation you can indicate that you'd like the parts of the UI that *ask* for those other bits of data to refresh.
<commit_msg>Add link to tutorial for app db.<commit_after>= Untangled Client Docs
:source-highlighter: coderay
:source-language: clojure
:toc:
:toc-placement!:
:toclevels: 3
:sectlinks:
:sectanchors:
:sectnums:

ifdef::env-github[]
:tip-caption: :bulb:
:note-caption: :information_source:
:important-caption: :heavy_exclamation_mark:
:caution-caption: :fire:
:warning-caption: :warning:
endif::[]

ifdef::env-github[]
toc::[]
endif::[]

== Basic UI

Untangled uses Om, which in turn uses https://facebook.github.io/react/index.html[React^] underneath.

=== Creating a Custom React Class

The mechanism for creating components is the `defui` macro:

[source]
----
(defui ComponentClassName
  Object
  (componentWillUpdate [this nextprops nextstate] (println "Component will update"))
  (render [this]
    (dom/div nil "Hello world")))
----

This macro generates a React class as a plain JavaScript class, so it is completely compatible with the
React ecosystem.

Notice the use of `Object`. It indicates that the following method bodies (like in
http://clojure.org/reference/protocols[protocols^]) are being added to the
generated class. From an OO perspective, this is like saying \"my widget extends Object\". The `render`
method is the only method you need, but you can also add in your own methods or React lifecycle
methods.

=== React lifecycle methods

If you wish to provide
https://facebook.github.io/react/docs/component-specs.html#lifecycle-methods[lifecycle methods^], you can
define them under the Object section of the UI:

[source]
----
(defui WidgetWithHook
  Object
  (componentWillUpdate [this nextprops nextstate] (println "Component will update"))
  (render [this]
    (dom/div nil "Hello world")))
----

==== Lifecycle method signatures

For reference these are the signatures you should use for the React Lifecycle methods:

[source]
----
(initLocalState [this])
(componentWillReceiveProps [this next-props])
(componentWillUpdate [this next-props next-state])
(componentDidUpdate [this prev-props prev-state])
(componentWillMount [this])
(componentDidMount [this])
(componentWillUnmount [this])
----

=== ClojureScript and React – HTML differences

Here are some common things you'll want to know how to do that are different when rendering with Om/ClojureScript:

- Inline styles are specified with real maps `(dom/p #js { :style #js {:backgroundColor \"rgb(120,33,41)\"} } ...)`.
Note the nested use of raw Javascript maps. These are passed directly to React. Using cljs persistent data structures
won't work.
- CSS class names are specified with `:className` instead of `:class`.
- Any time there are adjacent elements of the same type in the DOM, they should each have a unique `:key`
attribute. This is typically generated by a function you supply to the Om factory function, but you can
also do it manually.

=== Element factory

In order to render components on the screen you need an element factory.
You generate a factory with `om/factory`, which will then
act like a new 'tag' for your DOM. We commonly prefix these factories with `ui-` so
we don't confuse them with query attribute names and other local bindings. If the
component is ever to be rendered in a list of adjacent elements then the factory should
be given a key function for generating unique React keys on the component.

[source]
----
(def ui-widget (om/factory Widget {:keyfn (fn [props] (get props :some-prop))}))
----

=== Rendering a Component, Sending, and Accessing Properties

You can now render a widget inside of any other component using `(ui-widget { :prop 1 })`.

You access properties in a component using `om/props`:"

[source]
----
(defui Widget
  Object
  (render [this]
    (let [{:keys [name]} (om/props this)]
      (dom/div nil (str "Hello " name)))))

(def ui-widget (om/factory Widget))

...
   (ui-widget {:name "Sally"})
----

=== Computed data like Callbacks

In plain React you store component local state and pass data from the parent to the child through props.
You also pass your callbacks through props. In Untangled, we need a slight variation of
this because a component can have a query that asks the underlying system for data.

If you complect callbacks and such with this queried data then you run into trouble because the rendering system
can re-render a component without going through the parent, meaning that callbacks could be lost.

So, in general *props are for passing data that the component requested from a query*.

As such, Om has an additional mechanism for passing things that were not specifically asked for in a query: Computed
properties.

For your Om UI to function properly you must attach computed properties to props via the helper function `om/computed`.
The child can look for these computed properties using `om/get-computed`.

=== Stateful components

Earlier we stress that your components should be stateless whenever possible. There are a few
notable exceptions that we have found useful (or even necessary):

- The Untangled support viewer shows each app state change. User input (each letter they type) can
be quite tedious to watch in a support viewer. Moving these kinds of interstitial form interactions
into local component state causes little harm, and greatly enhances support. Om automatically hooks up local
state to input fields when you use "uncontrolled" form elements (which means you didn't set value/checked).
- External library integration. We use stateful components like D3 visualizations.

==== Form inputs

Om already hooks local state to form elements. So, in fact, you have to override this to *not* use
component local state. For text controls we'd recommend you leave it this way. For other controls like
checkboxes it is probably best to override this.

==== External library state

See the D3 example in the Untangled Tutorial.

=== Built-in React DOM

All of the standard HTML tags have pre-built React components, accessible from the `om.dom` namespace.

[source]
----
(ns ui
  (:require [om.dom :as dom]))

(defui Widget
  Object
  (render [this]
    (dom/div nil (str "Hello " name))))
----

== Application Database Format

Untangled applications use the default Om database format. This is a simple graph database format made from
standard Clojurescript persistent data structures: Maps and vectors. The entire database is a map.
Check out the http://untangled-web.github.io/untangled/tutorial.html#!/untangled_tutorial.C_App_Database[tutorial] for more information.

=== Tables

Specific items in the database are stored in tables. Each table is indexed by a top-level key in the database.
Items in the database can refer to other items via a foreign reference, which is formatted as an Ident. It is also legal
to have top-level data that is not a table.

[source]
----
{:value 53
 :table/by-id { 1 { :id 1 :x 1 } } }
----

The only way to tell a table from a value is by convention. Tables will usually be named in a way that
indicates what the primary key of the table is (e.g. `by-id`), and will be maps of maps. Regular values can
be anything, including an Ident.

=== Idents

An Ident is nothing more than a two element vector, where the first entry is a keyword (the "name" of a database table)
and the second entry is the ID of the object in that table: `[:table-name id]`

In the database above you would describe the object in the table as `[:table/by-id 1]`.

=== Graph

Combining regular values, tables, and idents gives you the overall database format which can support any arbitrary
graph. The database below has a list of two people (via idents pointing to the people in the table), and each
person has a pointer to the person that is their mate. This creates a graph with a loop (when following mate).

[source]
----
{:my-list [ [:people/by-id 1] [:people/by-id 2] ]
 :people/by-id {
   1 { :db/id 1 :person/name "Tony" :person/mate [:people/by-id 2]}
   2 { :db/id 2 :person/name "Jill" :person/mate [:people/by-id 1]}}}
----

[ditaa,target=basic-db]
....
                                                  +-------------+
                                                  |             |
                                           Table  v             |
 +-------+      +-----------------+       +----------------+    |
 |my-list|----->| :people/by-id 1 |------>| 1  Tony    mate|-+  |
 +-------+      +-----------------+       |                | |  |
                | :people/by-id 2 |------>| 2  Jill    mate|-+--+
                +-----------------+       +----------------+ |
                                                 ^           |
                                                 |           |
                                                 +-----------+
....

== The Query Language

The query language is a subset of Datomic Pull syntax. It is a syntax that is designed to walk a graph and produce a
tree (which is suitable for a UI, which is naturally a tree).

Queries are written as a vector.

=== Attributes

The query `[:a :b :c]` means read the attributes `:a` `:b`, and `:c` from the current object. For example,
if this query was against the root of the graph, it would mean the top-level database itself should contain the
keys `:a`, `:b`, and `:c`. In the context of a join (or sequence of joins) it indicates attribute reads in that
context.

One may query any attribute that makes sense, including an entire table. For example, the query `[:people/by-id]`
against the database above will return:

[source]
----
{ :people/by-id { 1 { :db/id 1 :person/name "Tony" :person/mate [:people/by-id 2]}
                  2 { :db/id 2 :person/name "Jill" :person/mate [:people/by-id 1]}}}
----

=== Joins

Joins can be done against reference typed attributes (which essentially means an attribute holding an ident).

Joins are written as a map, where the key is the join point, and the value is a sub-query: `[{:my-list [:person/name]}]`. If
the join point is a vector of idents, then it is a to-many join and the query will result in multiple values. If
the join point is a single ident, then it is a to-one join, and the query will result in a single value. In the
context of our database above this query should return the names of the people in my list.

The join shown in the prior paragraph against our database above would result in:

[source]
----
{ :my-list [ {:person/name "Tony"} {:person/name "Jill"} ] }
----

=== Recursion

Queries can be recursive. In the case where the graph has a normal termination point (such as bullet lists) you
can use `...` to indicate a recursive join: `[{:list [:item/name {:sublist ...}]}]`

This would return a nested map that would follow the graph database links and possibly return something like this:

[source]
----
{ :list { :item/name "A"
          :sublist [ { :item/name "A.1" }
                     { :item/name "A.1" :sublist [ { :item/name "A.1.1" } ]}]}}
----

In our database from earlier, we have a loop. The query engine will automatically detect loops and stop, but you can manually
limit the recusion depth using a number instead of `...`: `[{:my-list [:person/name {:person/mate 1}]}]`
which would result in:

[source]
----
{ :my-list [ { :person/name "Tony" :person/mate { :person/name "Jill" } }
             { :person/name "Jill" :person/mate { :person/name "Tony" } } ]}
----

=== Unions

Union queries are used strictly as the subquery on joins, and are represented by a map. The keys of the map represent
the possible choices of subquery to run, and the value represents the subquery.

In the case of a union query one must realize that it is impossible to say what the query means until you look at the
actual database. Here is how they work:

. Examine the Ident at the join point of the join. Extract the keyword from that ident.
. Use the ident from (1) to look up the subquery from the union.
. Continue processing the query using that subquery

==== Union Example

Assume the following simple database:

[source]
----
{ :things [ [:people/by-id 1] [:animals/by-id 1] ]
  :people/by-id { 1 { :id 1 :type :person :name "Joe" } }
  :animals/by-id { 1 { :id 1 :type :dog :breed "Poodle" } } }
----

The following query: `[{:things { :people/by-id [:type :name]
                                  :animals/by-id [:type :breed] }}]`

would see the to-many join of `:things`, and for each element it would select the proper subquery. Resulting in:

[source]
----
[ { :type :person :name "Joe" }
  { :type :dog :breed "Poodle" } ]
----

Unions work fine on to-one joins exactly the same (returning only one result).

=== Query parameters

The query language includes support for adding a parameter map to every kind of query element. Untangled does not
support such parameters on the UI; however, since the same query language is used with respect to the server, it is
useful to know how to represent them.

Basically, you surround the query element with parens, and add a map as the second entry.

A property with a parameter: `[(:prop { :param 1})]`
A join with a parameter: `[({:prop [:a :b]} { :param 1})]`

Again, the the UI cannot make sense of these, but you can write such queries to the server and interpret them there.

== Initial Application State

Building your initial application state can be done in one of three ways. The recommended approach is to co-locate the
application state on the components that will use it. You may also hand-build either a tree (which can be
auto-normalized by the UI components into a graph). Finally, you may hand-build a graph database in the format described
earlier.

All three methods should result in a graph database. They are just different approaches at initial input, with different
pros/cons.

In all cases you must ensure that the components have Ident implementations that match up with your graph structure.

=== Using InitialAppState

This is probably the easiest method to code, and the easiest to keep straight during development because the data
is co-located with the queries and UI bits. The only disadvantage is that you cannot easily initialize parts of the
graph that do not have a UI representation (which is probably rare).

Implement the `InitialAppState` protocol on your ui components, and compose the initial state together just like you
do with queries:

[source]
----
(defui Child
  static uc/InitialAppState
  (initial-state [clz params] { :a 1 })
  ...)

(defui Parent
  static uc/InitialAppState
  (initial-state [clz params] { :x 1 :child (uc/initial-state Child) })
  ...)
----

Compose these all the way to your root component. Untangled will detect state on your root component, and use that
to construct the initial application database.

==== Unions and InitialAppState

To-one unions (e.g. used in tabbed interfaces) are automatically resolved if the branches of the union all define
InitialAppState implementations. The union component InitialAppState should define the "default" branch of the union.

=== Using a manually-constructed graph db

Simply create your database in a map, then *wrap it in an atom* and pass that via the `:initial-state` parameter of
`new-untangled-client`. This method is a bit of a hassle to maintain, but allows you to place things in the database
that are not (yet) in your UI.

=== Using a manually-constructed tree

Create a tree of data in a map. Pass it (not wrapped in an atom) to `:initial-state`. This technique is probably the
least useful. It is no more functional than the `InitialAppState` method, but is harder to maintain.

== Mutations

Untangled uses the abstract top-level transactions modelled by Om to evolve your application state. One should view
mutations as a function that evolves the state of the database:

[ditaa,target=mutations]
....
   /-----\                  /-----\
   | DB  |                  | DB' |
   |     |-----mutation---->|     |
   \-----/                  \-----/
....

Remember that almost everything in your database should be in a table. Mutations run in the context of components (or
can take parameters), which means that mutations can be given sufficient context (e.g. an ident of the thing to change)
to be fully abstract. An operation like `set-date-to-todate` might take the ident of a calendar widget. It need only
go to that place in the database and change the state there.

=== Built-in mutations

The following functions are built in (in `untangled.client.mutations`), and should generally only be used in the context of UI state changes (e.g.
folding, checkbox toggle, etc.). They invoke an internal transaction.

WARNING: You should not use these for bit-twiddling your real state! Define your own top-level abstract transactions.
These functions are really meant as convenience when dealing with controlled form inputs whose state is in your app
state.

- `(set-string! component field [event|value])`
- `(set-integer! field [event|value])`
- `(set-value! component field value)`
- `(toggle! component field)`

The first two take a value or event via a named parameter. For example `(m/set-string! this :name :event evt)` where
`evt` is a javascript input field event will extra the input's value and store it in the app db on the correct table
entry. These functions are really meant for working with form field state stored in the app database (as opposed to
component local state in uncontrolled form inputs).

=== Custom mutations

Untangled provides a multimethod that you can hook your own mutations into.

[source]
----
(ns app.mutations
  (:require [untangled.client.mutations :as m]))

(defmethod m/mutate 'my/mutation-symbol [env k params]
   { :action (fn[] ...) })
----

The three parameters are:

. `env`: The mutation environment. This is a map that contains:
-- `state`: The current app database atom. Use `swap!` to modify it
-- `ref`: The ident of the component that invoked the transaction
. `k`: This is the symbol, which is identical to the multimethod dispatch value (generally ignored)
. `params`: The parameters passed to the mutation

WARNING: The body should *not* side-effect! It should instead return a map. The map can contain:

- `:action`: A lambda function to run that will actually do the side-effects
- One or more remote indicators. Typically something like `:remote true`. See the section on remote mutations.

=== Invoking a mutation (`transact!`)

The `om/transact!` function is used to run a top-level transaction, and can invoke any number of mutations (in order).
It must be given a component reference or reconciler (typically the former) and a transaction to run. This looks just
like the query notation, but looks to include method calls (which will invoke the multimetod by symbol):

[source]
----
(om/transact! this '[(my/mutation-symbol {:x 1}) (other/mutations)])
----

The mutations in a transaction will run in order. Any of them that indicate a remote nature will be sent across the
wire to the server.

=== Post mutation hooks (experimental)

The is a multimethod for adding in post-mutation handlers that will run after the main mutation. These can be useful
when there is a common behavior that should happen after some set of mutations.

=== UI refresh after mutation

Untangled uses Om to manage the UI, and as such the UI refresh story is Om's story. The basic
rule is that when you `transact!`, the component (subtree) used for the transaction will be refreshed in the UI. This
allows you to automatically handle a lot of UI updates without having to think much; however, there are a couple of
general rules and tools you can use when this alone is insufficient.

. Move the transaction to a parent, and pass a callback that invokes (the parent's) transaction in the child. This
technique composes well (the parent has to know about the child, but the child need only support the abstract idea
of providing a callback hook). This is the most common technique in list management, where a child might have a delete
button, but the delete really needs to happen on the parent's list.
. Use follow-in reads

==== Follow-on Reads

The name "follow-on reads" is meant to describe the abstract way of refreshing the UI without thinking specifically
about the UI. A follow-on read is a way to indicate what (typically derived) data should be re-read from your
application database after a mutation. For example, if you have a friend list and you add someone to it, you might
need to re-read the count of friends for some indicator somewhere else on the screen. It is easy to reason about
the concept that the mutation `add-friend` affects the database value `:friend-count` (which you can explicitly store
as a denormalized value after each mutation, or derive in the UI by pulling in the list of friends and counting them).

Independent of how you store data in your database, you know what you've changed in a mutation. So, when you run
a mutation you can indicate that you'd like the parts of the UI that *ask* for those other bits of data to refresh.

{'fraction_non_alphanumeric': 0.09067070823710546, 'fraction_numerical': 0.0025019245573518092, 'mean_word_length': 3.3802950474183353, 'pattern_counts': {'":': 0, '<': 3, '<?xml version=': 0, '>': 11, 'https://': 4, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 26, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5125664', 'n_tokens_mistral': 11256, 'n_tokens_neox': 10835, 'n_words': 5979}