Widgets

Widget objects should subclasses of reblocks/widget:widget class also, minimally you have to define a method for the reblocks/widget:render generic-function. This function should return use reblocks/html:with-html macro to render the widget.

Other parts of API around widgets are:

Example

To define a widget, use reblocks/widget:defwidget macro. It creates a class with a proper meta-class. Old Weblocks version used this metaclass to discover changes slots, and probably this feature will be returned back some day.

CL-USER> (reblocks/widget:defwidget hello ()
           ((name :initarg :name
                  :reader get-name)))
#<REBLOCKS/WIDGETS/MOP:WIDGET-CLASS COMMON-LISP-USER::HELLO>

CL-USER> (defmethod reblocks/widget:render ((widget hello))
           (reblocks/html:with-html
             (:span ("Hello ~A" (get-name widget)))))
#<STANDARD-METHOD REBLOCKS/WIDGET:RENDER (HELLO) {1004E27BC3}>

Then call this, to run a webserver and preview your widget in the browser:

CL-USER> (reblocks/preview:preview
          (make-instance 'hello
                         :name "Bob"))

A result will look like this:

API

Base class for all widget objects.

macro
name direct-superclasses &body body

A macro used to define new widget classes. Behaves exactly as defclass, except adds reblocks/widgets/mop:widget-class metaclass specification and inherits from reblocks/widget:widget if no DIRECT-SUPERCLASSES are provided.

Define this method to render widget's content.

Use reblocks/html:with-html macro to render HTML. You can use any other templating engine, just ensure it writes output to reblocks/html:*stream*

Outer DIV wrapper will be added automaticall, see get-html-tag generic-function. It will have CSS tags returned by get-css-classes generic-function.

generic-function
w &key inserted-after inserted-before removed

This method should be called to update widget on a client.

Usually this required as a result of an action execution.

In the original Weblocks there was a mark-dirty method. This one replaces it. To make everything easier, the new protocol excludes "propagation". If you need to update other widgets, please define an "update" method for your widget. You can use :before or :after modifiers, to keep the current behavior and to add propagation code.

There are a few optional arguments to control the way how does widget should be updated. They can be useful to not update the whole parent widget.

  • If one of INSERTED-AFTER or INSERTED-BEFORE is given, it should be a widget object to be used as an anchor. This can be useful to not rerender all children of some "list" widget when you adding a new element.

  • When REMOVED argument is T the widget will be removed from the DOM tree.

This method determines the enclosing tag of the widget.

The return value should either be a keyword like :div, which will be the enclosing tag, or a list of the form (:tag . attributes), where :tag is the enclosing tag (like :div) and attributes is a property list.

The attributes property list has keywords for keys, corresponding to the attribute name and the values are the values of the attribute.

For example:

  • :div - generates <div ...> widget content </div>;

  • (:div :display "flex") - generates (<div ... :display "flex">widget content</div>.

Note on attributes: in the attribute list the following attributes can not be specified, they will be ignored:

  • :class - Use the get-css-classes generic-function to specify these;

  • :id - This is the value of the dom-id slot of the widget, normally automatically managed by reblocks.

The default implementation returns - :td - inside a table row; - :tr - inside a table; - :div - by default.

Returns a list of classes for the widget. Classes may be a strings or a keywords. By default, :widget and keyworded class name are returned. Use (list* :new-class (call-next-method)) to add new classes.

Methods of this generic should return an instance of subclass of reblocks/widget:widget The most obvious cases are transformation of strings and functions into the widget, but these methods are already supplied by Reblocks.

If reblocks/page:init-page returns an object, then create-widget-from will be called on it to create the root widget.

String widget

This is a simple type of widget which can be made out of any string.

Create a widget from a string.

Whether to escape the output for HTML.