Make light work of similar-looking pages

There are common user interface elements present on all the different URLs of a web application. Our previous example is the first one with more than one page. We dealt with the commonality between its pages by having a common class (AddressBookPage) from which the page used by each View inherit all the common elements.

In a large UserInterface it becomes cumbersome to do what we’ve done with AddressBookPage. Moreover, what we did also hard-codes the main layout (and usually, look) used for your application in the code of the UserInterface. As you will learn later on, it is also possible to re-use other pre-existing UserInterfaces as part of your web application.

If you intend for a UserInterface to be re-usable in different web applications, each with its own look and main layout, you cannot hard-code what the final web page will look like.

Slots and Views without pages

For all these reasons, there’s another way to deal with many pages that look similar: You can attach a page to the entire UserInterface instead of to each individual View inside it. Then you only need to specify as part of each View what that View adds to the page.

To make this possible, there is a special Widget, Slot. On its own, a Slot does not render anything at all on the page it is a part of. It represents an empty area, the contents of which is meant to be supplied by a View. The View then “plugs” only the bit of content specific to it into the supplied Slot, on the fly.

There can be more than one Slot on a page, and each one of then is referred to individually by name.

../_images/views.png

A page with two different views.

See it in action

Below is the source code for an application that demonstrates these ideas.

The application has two Views . Its page (a CustomPage) contains an HMenu (a horizontal menu) which allows one to navigate between the two Views of the application.

The home page looks as follows:

../_images/slots1.png

Notice the two bits of text. Each paragraph was plugged into a separate Slot of the page.

In “Page 2”, the same page is displayed, but with different text in those Slots:

../_images/slots2.png


from __future__ import print_function, unicode_literals, absolute_import, division
from reahl.web.fw import UserInterface
from reahl.web.ui import HTML5Page, P, Menu, HorizontalLayout
from reahl.web.layout import PageLayout
from reahl.web.pure import ColumnLayout, UnitSize


class MyCustomPage(HTML5Page):
    def __init__(self, view, bookmarks):
        super(MyCustomPage, self).__init__(view, style='basic')

        self.use_layout(PageLayout())
        contents_layout = ColumnLayout(('secondary', UnitSize('1/4')), 
                                       ('main', UnitSize('3/4'))).with_slots()
        self.layout.contents.use_layout(contents_layout)

        menu = Menu(view).use_layout(HorizontalLayout()).with_bookmarks(bookmarks)
        self.layout.header.add_child(menu)


class SlotsUI(UserInterface):
    def assemble(self):

        home = self.define_view('/', title='Page 1')
        home.set_slot('main', P.factory(text='In this slot will be some main content for the view on /'))
        home.set_slot('secondary', P.factory(text='Some secondary content related to /'))

        another = self.define_view('/page2', title='Page 2')
        another.set_slot('main', P.factory(text='This could, for example, be where a photo gallery shows a large photo.'))
        another.set_slot('secondary', P.factory(text='Thumbnails will then sit on the side of the big photo.'))

        bookmarks = [home.as_bookmark(self), another.as_bookmark(self)]
        self.define_page(MyCustomPage, bookmarks)

In the example, the PageLayout is used to give our plain HTML5Page a .header (which we can use to put a menu bar) and contents area. The contents are in turn laid out using a ColumnLayout. The column named “main” is to the right, and fairly large, whereas “secondary” sits to the left of it, and is narrower.

The ColumnLayout also adds Slots in each column so that we can use the columns without having to hard-code their contents. The PageLayout does the same for the header and footer areas.

In this example, a CustomPage is derived from HTML5Page. That way the PageLayout can be applied to our CustomPage, and a suitably laid out Menu can be added to the .header of all CustomPage instances.