defview - Defining Om Next components in a compact wayOm Next views are a combination of an Om Next component defined
with om.next/defui and a component factory created with
om.next/factory. The defview macro combines these two into
a single definition and reduces the boilerplate code needed to
define properties, idents, React keys, queries and component
functions.
Views are defined using defview, accepting the following
information:
key or keyfn function (optional)validate or validator function (optional)query, ident, componentWillMount
or render).A (defview UserProfile ...) expression defines both a
UserProfile component and a user-profile component
factory.
All properties declared via the queries are made available in
component functions via an implicit let statement wrapping the
original function body in the view definition.
As an example, the properties query
[user [name email {friends ...}] [current-user _]]
would destructure the resulting properties as follows:
:user/name -> name
:user/email -> email
:user/friends -> friends
:current-user -> current-user
The defview macro predefines (query ...) for any view based
on the properties query. Auto-generation currently supports joins,
links, parameterization but no unions.
As an example, the properties query
[user [name email {friends User}] [current-user _]]
would generate the following query function:
static om.next/IQuery
(query [this]
[:user/name
:user/email
{:user/friends (om/get-query User)}
[:current-user _]])
This can be overriden simply by implementing your own query:
(defview User
[...]
(query
[:name :email]))
In the future, we will likely add a simple way to transform
auto-generated queries. On idea is to implicitly bind the
auto-generated query when overriding query and providing
convenient methods to parameterize sub-queries, e.g.
(query
(-> auto-query
(set-param :user/friends :param :value)
(set-param :current-user :id [:user 15])))
ident and :keyfnIf the properties query includes [db [id]], corresponding to
the Om Next query attribute :db/id, it is assumed that the
view represents data from DataScript or Datomic. In this case,
defview will automatically infer (ident ...) and
(key ...) / :keyfn functions based on the database ID. This
behavior can be overriden by specifically defining both ident
and key.
As an example:
(defview User
[db [id] user [name]])
will result in the equivalent of:
(defui User
static om/Ident
(ident [this {:keys [db/id]}]
[:db/id id]))
(def user (om/factory User {:keyfn :db/id}))
this and props in functionsThe names this and props are available inside
function bodies depending on their signature (e.g. render
only makes this available, whereas ident pre-binds this
and props).
By default, defview implicitly assumes the arguments to custom
functions, i.e., functions other than Om Next and React lifecycle
functions, are [this]. However, when adding JS object functions
to a view, you'll often want additional arguments. Here is an example
highlighting the problem:
(defview UserList
[users]
(select ;; implictly adds [this]
;; where should the user ID come from?
(om/transact! this `[(users/select {:user ~???})])))
To solve this problem, defview supports a . syntax for custom
function definitions. Any function that starts with a . will
become a JS object function and its arguments will remain untouched:
(defview UserList
[users]
(.select [this user]
(om/transact! this `[(users/select {:user ~user})])))
Inside the view, this function can now be called with
(.select this <user id>), just like any other JS object function.
(ns foo.bar
(:require [workflo.macros.view :refer [defview]]))
(defview User
[user [name email address {friends ...}]]
[ui [selected?] select-fn]
(key name)
(validate (string? name))
(ident [:user/by-name name])
(render
(dom/div #js {:className (when selected? "selected")
:onClick (select-fn (om/get-ident this))}
(dom/h1 nil "User: " name)
(dom/p nil "Address: " street " " house))))
Example usage in Om Next:
(user (om/computed {:user/name "Jeff"
:user/email "jeff@jeff.org"
:user/address {:street "Elmstreet"
:house 13}}
{:ui/selected? true
:select-fn #(js/alert "Selected!")))
Can you improve this documentation?Edit on GitHub
cljdoc builds & hosts documentation for Clojure/Script libraries
| Ctrl+k | Jump to recent docs |
| ← | Move to previous article |
| → | Move to next article |
| Ctrl+/ | Jump to the search field |