reblocks-navigation-widget
2024-10-12
A container widget which switches between children widgets when user changes an url.
Upstream URL
Author
License
Reblocks Navigation Widget
REBLOCKS-NAVIGATION-WIDGET ASDF System Details
- Description: A container widget which switches between children widgets when user changes an url.
- Licence: Unlicense
- Author: Alexander Artemenko svetlyak.40wt@gmail.com
- Homepage: https://40ants.com/reblocks-navigation-widget/
- Bug tracker: https://github.com/40ants/reblocks-navigation-widget/issues
- Source control: GIT
- Depends on: log4cl, reblocks, str
Installation
You can install this library from Quicklisp, but you want to receive updates quickly, then install it from Ultralisp.org:
(ql-dist:install-dist "http://dist.ultralisp.org/"
:prompt nil)
(ql:quickload :reblocks-navigation-widget)
Usage
This addon for Reblocks frameworks allows you to define which widgets should be
shown to the user dependening on URL
's path.
The main entry-point is defroutes
macro. Use it to define a subclass of
navigation widget and then return this widget from the session initialization
method of your Reblocks application.
Nested routes
Starting from version 0.9.0, the library supports nested routes. This allows you to combine routes defined in separate systems.
For example, lets pretend we have a separate ASDF
system for user management.
It defines it's routes like this:
(defroutes users ("/" (make-user-list)) ("/add" (make-new-user-form)))
And now, if we want to incorporate this user management app into our app having it's own routing, we can do this by using a prefix rule:
(defroutes main ;; a subroutes ((:prefix "/users") (make-users)) ;; a usual widget ("/stats" (make-stats)))
In it's turn, MAIN
router could be used in app having it's own PREFIX
/admin
. Here is how
this nested setup will be processed by navigation widgets.
When user opens a page with URI
/admin/users/add
, then MAIN
widget will be rendered
first. It will see the app has /admin
prefix and will cut it from the URI
. Then MAIN
routes
widget will check /users/add
against it's rules and will create USERS
widget. RENDER
method
of USERS
widget will be called with *current-path*
set to /admin/users
. In it's turn,
USERS
widget will cut /admin/users
prefix from the whole URI
/admin/users/add
and will check
/add
against it's rules to find out it need to create a NEW-USER-FORM
.
API
macro reblocks-navigation-widget:defroutes
class-name &body rules
Defines a new class with name CLASS-NAME
, inherited from navigation-widget
.
And a function make-{class-name}
to make instances of this class.
Each entry in rules should be a list of two items. First item is a regex pattern to match URL
path.
Second item is a form to create a widget. A new widget will be created only if URL
was changed.
Here is an example of a widget with two rules:
(defroutes tasks-routes
("/tasks/d+" (make-task-page))
("/tasks/" (make-task-list "Make my first Reblocks app"
"Deploy it somewhere"
"Have a profit")))
With these rules, when user opens URL
/tasks/
a widget returned by MAKE-TASK-LIST
will be set as current-widget
and shown to the user. If user clicks on some task
and URL
change to /tasks/100500
, then a widget for a task will be created by a call
to MAKE-TASK-PAGE
.
Pay attention that widget creation form is responsible for extraction of the parameters
from the URL
. In above case, MAKE-TASK-PAGE
should call REBLOCKS/REQUEST:GET-PATH
and
parse path to extract task's id. Probably this will change in future defroutes will catch
matched path pieces.
class reblocks-navigation-widget:navigation-widget
(widget)
Base class for all navigation widgets.
When rendered it tracks if URL
was changed and
creates a new child widget according to given navigation rules.
Usually you don't want to inherit from this class manually,
but instead use defroutes
macro.
reader reblocks-navigation-widget:current-widget
(navigation-widget) (= nil)
reader reblocks-navigation-widget:current-path
(navigation-widget) (= nil)
A whole path including the app's prefix.