For shadow-cljs users, the easiest way to get portal setup is via a preload. It allows you to inject a namespace for instrumentation during development.
Note This guide will focus on ClojureScript in the context of a web browser, but shadow-cljs supports other JavaScript environments.
portal.web
vs portal.shadow.remote
This first question you need to answer is, do you want Portal hosted by the web page itself or do you want to send values to a remote instance using the remote-api?
The pros and cons of portal.web
are:
The pros and cons of portal.shadow.remote
are:
Note You can run both types at the same time without any issues.
With that in mind, let's get started. In your shadow-cljs.edn
file, you need
to add the following bit of configuration:
;; shadow-cljs.edn
{:builds
{:build-id
{:target :browser
...
:build-hooks [(portal.shadow.remote/hook)]
:devtools {:preloads [portal.shadow.preload]}}}}
Or if you would like to pass options to portal.api/start
:
;; shadow-cljs.edn
{:builds
{:build-id
{:target :browser
...
:build-hooks [(portal.shadow.remote/hook {:port 1234})]
:devtools {:preloads [portal.shadow.preload]}}}}
To define a custom preload change the configured preload to your custom namespace.
A basic setup with portal.web
is as follows:
(ns my-app.portal.setup
(:require [portal.web :as p]))
;; Allows options to be propagated across page reloads
(p/set-defaults! {:theme :portal.colors/gruvbox})
(add-tap p/submit)
Note To quickly open the Portal UI, you can use the
ctrl | cmd + shift + o
shortcut from the parent page.
A basic setup with portal.shadow.remote
is as follows:
(ns my-app.portal.setup
(:require [portal.shadow.remote :as p]))
(add-tap p/submit)
For a more comprehensive setup, try the following which leverages both and some additional bits from other guides:
(ns my-app.portal.setup
(:require [portal.shadow.remote :as r]
[portal.web :as p]))
(defn- submit [value]
(p/submit value)
(r/submit value))
(defn- error->data [ex]
(merge
(when-let [data (.-data ex)]
{:data data})
{:runtime :portal
:cause (.-message ex)
:via [{:type (symbol (.-name (type ex)))
:message (.-message ex)}]
:stack (.-stack ex)}))
(defn- async-submit [value]
(cond
(instance? js/Promise value)
(-> value
(.then async-submit)
(.catch (fn [error]
(async-submit error)
(throw error))))
(instance? js/Error value)
(submit (error->data value))
:else
(submit value)))
(add-tap async-submit)
(defn- error-handler [event]
(tap> (or (.-error event) (.-reason event))))
(.addEventListener js/window "error" error-handler)
(.addEventListener js/window "unhandledrejection" error-handler)
Can you improve this documentation? These fine people already did:
Chris Badahdah & Graham CarlyleEdit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close