Introduction to Tiles

plone.tiles implements low-level, non-Plone/Zope2-specific support for creating “tiles” in the Deco layout system.

For the purposes of this package, a tile is a browser view and an associated utility providing some metadata about that view. The metadata includes a title and description, an ‘add’ permission and optionally a schema interface describing configurable aspects of the tile. The idea is that a UI (such as Deco) can present the user with a list of insertable tiles and optionally render a form to configure the tile upon insertion.

A tile is inserted into a layout as a link:

<link rel="tile" target="placeholder" href="./@@sample.tile/tile1?option1=value1" />

The sub-path (tile1 in this case) is used to set the tile id attribute. This allows the tile to know its unique id, and, in the case of persistent tiles, look up its data. sample.tile is the name of the browser view that implements the tile. This is made available as the __name__ attribute. Other parameters may be turned into tile data, available under the data attribute, a dict, for regular tiles. For persistent tiles (those deriving from the PersistentTile base class), the data is fetched from annotations instead, based on the tile id.

There are three interfaces describing tiles in this package:

  • IBasicTile is the low-level interface for tiles. It extends IBrowserView to describe the semantics of the __name__ and id attributes.
  • ITile describes a tile that can be configured with some data. The data is accessible via a dict called data. The default implementation of this interface, plone.tiles.Tile, will use the schema of the tile type and the query string (self.request.form) to construct that dictionary. This interface also describes an attribute url, which gives the canonical tile URL, including the id sub-path and any query string parameters. (Note that tiles also correctly implement IAbsoluteURL.)
  • IPersistentTile describes a tile that stores its configuration in object annotations, and is needed when configuration values cannot be encoded into a query string. The default implementation is in plone.tiles.PersistentTile. To make it possible to have several tiles of a given type on the same layout, the annotations are keyed by the tile __name__.

In addition, tiles are described by ITileType, which contains attributes for the tile name, title, description, add permission and schema (if required).

A properly configured tile, then, consists of a browser view providing IBasicTile or one of its derivatives, and a utility providing ITileType with the same name as the tile browser view. There is a convenience ZCML directive - <plone:tile /> - to register both of these components in one go.

To support creation of appropriate tile links, plone.tiles.data contains two methods - encode() and decode() - to help turn a data dictionary into a query string and turn a request.form dict into a data dict that complies with a tile’s schema interface.

Creating a Simple Tile

The most basic tile looks like this:

from plone.tiles import Tile

class MyTile(Tile):

    def __call__(self):
        return u"<html><body><p>Hello world</p></body></html>"

Note that the tile is expected to return a complete HTML document. This will be interpolated into the page output according to the following rules:

  • The contents of the tile’s <head /> section is appended to the output document’s <head /> section.
  • The contents of the tile’s <body /> section will replace the tile placeholder as indicated by the tile link.

Note that this package does not provide these interpolations. For a Plone implementation of the interpolation algorithm, see plone.app.blocks

If you require a persistent tile, subclass plone.tiles.PersistentTile instead. You may also need a schema interface if you want a configurable transient or persistent tile.

To register the tile, use ZCML like this:

<configure xmlns:plone="http://namespaces.plone.org/plone">

    <plone:tile
        name="sample.tile"

        title="A title for the tile"
        description="My tile's description"
        add_permission="my.add.Permission"
        schema=".interfaces.IMyTileSchema"

        class=".mytile.MyTile"
        permission="zope.Public"
        for="*"
        layer="*"
        />

</configure>

The first five attributes describe the tile by configuring an appropriate ITileType directive. The rest mimics the <browser:page /> directive, so you can specify a template file and omit the class, or use both a template and class.

If you want to register a persistent tile with a custom schema, but a template only, you can do e.g.:

<plone:tile
    name="sample.persistenttile"
    title="A title for the tile"
    description="My tile's description"
    add_permission="my.add.Permission"
    schema=".interfaces.IMyTileSchema"
    class="plone.tiles.PersistentTile"
    template="mytile.pt"
    permission="zope.Public"
    for="*"
    />

If you want to override an existing tile, e.g. with a new layer or more specific context, you must omit the tile metadata (title, description, add permission or schema). If you include any metadata you will get a conflict error on Zope startup. This example shows how to use a different template for our tile:

<plone:tile
    name="sample.persistenttile"
    template="override.pt"
    permission="zope.Public"
    for="*"
    layer=".interfaces.IMyLayer"
    />

See tiles.rst and directives.rst for more details.

Plone’s Specific Implementation of Tiles

plone.app.tiles is Plone’s UI integration for plone.tiles.

This package contains the following things:

  • A view @@add-tile, and an associated form, which can be used to create a new tile based on the tile’s schema. For transient tiles, this merely redirects to a URL with an appropriate query string. For persistent tiles, it will also save the necessary data. This will fire an IObjectCreatedEvent as well as an IObjectAddedEvent for the newly created tile (a transient object) when successfully submitted. In the case of the IObjectAddedEvent, the newParent attribute will be the tile’s context, and the newName attribute will be the tile’s id.
  • The @@add-tile view, when accessed directly, allows the user to choose from all available tiles (subject to the tile’s add permission) and redirects to the appropriate @@add-tile/<tile-type> URL to configure the tile.
  • A view @@edit-tile, and an associated form, which can be used to edit a tile based on the tile’s schema. This will fire an IObjectModifiedEvent for the modified tile (a transient object) when successfully submitted.
  • A view @@delete-tile, where the user may select a tile type, enter a tile id, and opt to clear out any persistent data for that tile. This can also be called by AJAX code given appropriate request parameters. This will fire an IObjectRemovedEvent for the removed tile (a transient object). The oldParent attribute will be the tile’s context, and the oldName attribute will be the tile’s id.

The default add and edit forms should suffice for most use cases. You can use plone.autoform to configure alternative widgets, either by hand or via plone.directives.form.

If you need a custom form, you can register an add view as an adapter from (context, request, tileType), where tileType is an instance providing plone.tiles.interfaces.ITileType.

The actual integration of the various views is left up to other packages (such as the Deco editor).

Table Of Contents

Previous topic

Introduction to Blocks

Next topic

Introduction to Toolbar

This Page