In many projects we have a need to display Location based breadcrumbs. Each breadcrumb needs to be able to:
Important thing to note here is that there are two scenarios how a user can end up in a specific view:
Big part of this was exploring how flexible this feature should be. And turns out that there are a lot of it depends factors.
Let's assume we are building an ecommerce. That ecommerce has categories and items assigned to categories. A url to a specific item could look somewhat like this:
/#/shop/category/fruits-111/category/citrus-222/item/lemon-999
This way we specify a full location path to an item. But if we assume that each category has exactly one parent (except the root categories) then we are free to leave out only one category:
/#/shop/category/citrus-222/item/lemon-999
We can squash it even more if we assume that each item has only one category (or we are able to reliably choose the main one):
/#/shop/item/lemon-999
So the first scenario is ideal for knowing what info to query from the backend. We simply destructure the url for the three ids and query the backend for their respective data.
In any other case however we'll need a recursion of sorts that will be sure to know the whole path. That could be either by the BE on its own (however that's not ideal as that way we couple FE navigational map with BE) or we let BE return relevant info about that node and we can let FE decided if that the end of the loop.
But even if we are fine with long urls they still have other drawbacks. Imagine this very likely scenario:
In the home page of the shop we have categories listing in a sidebar and all products listing in the main screen.
That way, in order to build a redirect url for lemon-999
product, we still need to query for its tree ancestors.
In the example above we saw that a shop item can be preceded by any number of categories. That means that when querying
for data we have to be prepared that the appdb will be populated with, probably, a collection of category
maps.
But in other domains we might have a structure that is far simpler. Take a school registry as an example:
school-111/grade-222/student-1337
. We know that the structure is always school->grade->strudent
. That way our appdb
could be populated with something as simple as
{:student {.. ..} :grade {.. ..} :school {.. ..}}
Because of all the complexity this feature involves, the template will only be given:
The missing piece - where to get the breadcrumbs data from - will have to be individually applied given the specific project domain.
However I assume that using re-frame-async-flow-fx
might be helpful:
(defn- set-breadcrumbs-event-fx
[{:keys [db]} [_ category-id id]]
{:pre [(:category db)
(:shop-item db)]}
{:dispatch [::breadcrumbs/set
[{:title "Shop"
:url "/#/shop"}
{:title (get-in db [:category :name])
:url (str "/#/shop/" category-id)}
{:title (get-in db [:shop-item :name])
:url (str "/#/shop/" category-id "/" id)
:disabled true}]]})
(rf/reg-event-fx ::set-breadcrumbs set-breadcrumbs-event-fx)
(rf/reg-event-fx
::fetch-breadcrumbs
(fn [_ [_ category-id id]]
{:dispatch-n [[::hydrogen-demo.category/get category-id]]
:async-flow {:rules [{:when :seen-all-of?
:events [::got ::hydrogen-demo.category/got]
:dispatch [::set-breadcrumbs category-id id]}]}}))
(rf/reg-event-fx
::go-to-shop-item
(fn [{:keys [db]} [_ category-id id]]
{:dispatch-n [[::view/set-active-view :shop-item]
[::fetch-breadcrumbs category-id id]
[::get id]]
:db (dissoc db :shop-item)
:redirect (str "/#/shop/" id)}))
Can you improve this documentation?Edit on GitHub
cljdoc is a website building & hosting documentation for Clojure/Script libraries
× close