fast framework Help

Tutorial: Hello, Blog

In this tutorial we will create a simple blogging application. We will cover the main aspects of a ff based website and will end up with a ready-to-deploy application with a bespoke user interface, that allows your client to easily create and manage their blog posts.

Presenter

The basic building blocks of every webpage that ff outputs to the screen, are called presenter. A presenter can be as simple as a html file that just contains a fragment of html. Presenters can be compared to what is called a "component" in other frameworks. They are elements that serve a certain purpose and can be reused inside a project or even across projects.

ff already brings some ready-to-use presenters for common use cases with it, but for this tutorial, we'll create everything from scratch.

Our first presenter will present a blog post.

Create a folder called presenter inside system/plugins/myPlugin and in that folder a file called post.html and put the following content in it:

<h1>Hello, world</h1>

Compose your Website with Draftboard

To bring the presenter component to the screen, you need to use ff's Draftboard panel. It can be reached by clicking on the "compose" button in the top menu bar. You'll find your "hello"-presenter in the list of presenters clicking the "new presenter"-button

Find the item that represents our "post" presenter and drag it to the draftboard next to the existing item that is called "ff login multiuser". You should immediately see your presenter outputting 'hello, world' in the preview window.

You can repeat dragging new "post" presenters to the draftboard. You'll see your presenter being output several times repeating your message to the world over and over again. For our case that does not make a lot of sense, but it shows how the output is assembled by presenter components and that presenters can exist multiple times on the screen. You can remove elements from the draftboard by dragging them into the trash bin.

You can learn more about how to compose your website using draftboard in the chapter Draftboard of the concepts section.

Templating - Enhance our presenter with managed content

In order to make the dump html presenter smarter, we use a concept called DOM Templating.

You can read more about that concept in the section Templating.

Manage text

A very common use case is to make text of our website editable and/or make text manageable in multiple languages.

To manage text, DOM templating uses the data-ffText attribute. This will turn the text content of any element editable. We enhance our presenter to be able to make the headline editable by adding data-ffText="title"":

<h1 data-ffText="title">hello, world</h1>

the value of the data-ffText attribute can be an arbitrary identifier (we call them "section identifier" or short "section"). For our case the section is called "title"

Once the page is reloaded, you will see a widget next to "hello, world". Clicking on it will enable you to change the text.

See the chapter Text in the Templating section to learn much more about the use of data-ffText in DOM Templating.

Multi-language

ff has built in multilingual abilities. We control the website's languages in the settings panel. In the admin panel click on "settings". One of the first items in the settings list is called "languages". By default, a website's language is "english", but you can add languages, by clicking on the widget next to the string "english" and tick some more languages.

Back on the website panel you can see that when opening the text edit widget, you now have tabs to switch between languages.

Styling

To add stylesheets to your page, your plugin needs a "css" folder. Any .css or .less file inside that folder will be included in the page automatically by default. It's good practice to name the css file according to your presenter, if its scope is to style that component.

The root element of any presenter will have its name assigned as a class name (in our case "post"), and will get a unique id. If you have two "post" presenters in the draftboard, only the first one will have the id "post". You can change the id of a presenter by clicking its widget in the draftboard and changing the "id" value.

Create a folder called css inside system/plugins/myPlugin and a file called post.css inside that folder with the following content:

.post>h1{ font-size: 2em; } #post{ color:blue; }

Adding dynamic content

In order to make the html presenter a bit smarter, it can directly hook into backend code. By convention, if you create a php class with the same name and file name than the html file, those two files recognise each other and the html file becomes the template that gets parsed by that php file. A presenter class must extend the ffPresenter class to inherit all of its functionality.

Create a file called post.php inside system/plugins/myPlugin/presenter and put the following content in it:

<?php class post extends ffPresenter{}

In order to inject dynamic generated content into a html presenter template, we use the "data-ffMethod" attribute. It connects HTML DOM elements with methods of our presenter class. For our example we change our post.html template as follows:

<section> <div data-ffMethod="showDate"></div> <h1 data-ffText="title">hello, world</h1> </section>

Note that we have wrapped the entire presenter component in a <section> element. This is necessary because presenters must have exactly one root component

The data-ffMethod="showDate" attribute indicates, that the return value of a public method called showDate will be inserted into our span element. We change our post.php as follows:

<?php class post extends ffPresenter{ public function showDate(){ return (new DateTime())->format('Y-m-d H:i:s'); } }

After refreshing the page, you will see the current time before the headline.

See the chapter Method Hooks in the Templating section to learn much more about the use of data-ffMethod in DOM Templating.

Media content

Similar to text, a website also needs to access (managed) media content. To output media, DOM templating uses the data-ffMedia attribute. Let's extend our template like this :

<section> <div data-ffMethod="showDate"></div> <h1 data-ffText="title">hello, world</h1> <figure data-ffMedia></figure> </section>

The data-ffMedia attribute does (yet) not provide a ui by default. That's why nothing changed after reload. To add a (preliminary) ui, you can add an argument to the data-ffMedia attribute.

Arguments in DOM Templating attributes are passed as json objects. Note that in order to pass json inside an attribute, you have to set it in single quotes

<section> <div data-ffMethod="showDate"></div> <h1 data-ffText="title">hello, world</h1> <figure data-ffMedia='{"edit":true}'></figure> </section>

Now, after a reload you should see a widget that allows you to upload an image. Choose any image and click on the check icon to upload it. You can also delete the image by clicking on the trash bin icon next to it.

If you want to set the output image to a certain width, you can do it like so:

[...] <figure data-ffMedia='{"edit":true, "width":500}'></figure> [...]

The image is now maximum 500px wide. Note, that the originally uploaded image is never altered, so you can play with dimensions, without regrets.

See the chapter Media in the Templating section to learn much more about the use of data-ffMedia in DOM Templating.

Adding structure to the site

Until now our website contains of only one page. It's time to change this!

A basic building block of a structured website is a menu. To speed up the creation of our example, we will re-use some pre-built presenters.

In the compose panel drag two new presenters, one "ffBreadcrumbMenu" and one "ffMenu" to the draftboard. Both should be positioned above our "post" presenter.

The preview window should already show the output of those presenters.

Before we continue, let's quickly create a basic styling for the menu. Create a file "menu.css" inside the folder "css" containing the following:

.ffBreadcrumbMenu, .ffMenu{ padding:1em; } .ffMenu>ul{ display:flex; gap:1em; }

Now click on the widget with the title "create new node" and type "posts" and hit return, click again on the widget, type "about" and hit return again.

You have just created the first two nodes of your website. You can think of the nodes like folders in your filesystem. Infact, if you look into the "content" directory of your ff installation, you will find two folders, named "posts" and "about". By default, ff replicates the structure of your website in the filesystem and stores all the managed content in it.

Separation of content, structure and presentation logic

If you click on one of the nodes, that you have just created, you will notice that our post-presenter will show its default text "hello, world" and the media is gone.

In ff there is a strict separation of structure, content and presentation logic. This means, that our post-presenter only shows and edits the content of the node that it is actually looking at. If we use the menu to navigate to another node in the website's structure, the presenter is still there, but the content to present belongs to the node.

To test this, navigate the "about" node, and change text and media to something different from before. As you go back and forth between the "about" node and the root node (accessible by clicking on "fastframework" in our breadcrumb menu), you see, that the post-presenter is actually just presenting the content of those two different nodes (Check in your file browser to find the original media data).

Structure panel

Next, we want to create a post. This time we don't use our "create new node" widget (although we could do so), but we use the admin panel, called "structure", that allows us to get an overview of the structure of our website. In the panel you will find a diagram of the site structure consisting of a root node, the posts node and the about node.

Below posts there is a plus icon, that acts exactly as the "create new node" widget of our menu. Click on it and enter "my first post" and hit enter. the new node will appear below the posts node. Now click on the plus icon next to the "my first post" node enter "my second post" and hit enter.

We now have 2 post nodes within the posts node.

Rule based routing

In the preview window of your website you can now see, that navigating to posts in the menu will show the two posts as submenu items. Still, wherever we click, we see the post-presenter outputting its content.

We want to make sure, that out post-presenter only shows up, when we are browsing through our posts.

To do so, we need to define rules to tell ff when it should show the post presenter. This is done by so called modifiers in the compose panel.

The "new modifier" widget will list all available modifiers. Drag the modifier named "show by path" to the draftboard and position it close to the post-presenter.
Now if you click on the "show by path" widget in the draftboard, you can see a list of properties. Click in the space next to the property "starts with" and enter "posts" and hit enter.
The modifier's property is now stored. Now grab the small disc on top left of the modifier and drag it over to the blue disc of our post-presenter and drop it there. the two items are now connected. This means the modifier is applied to the presenter.

If you now click around in the menu, you will find that our post-presenter only shows up, when we're navigating in posts or its sub items. post shows only, "if the current path starts with 'posts'".

To prevent post from showing up also when we navigate the "posts" node itself, we just add another modifier with a different rule
Drag the modifier named "show by level" to the draftboard. Click on it, and type "2" next to the property "is" and hit return. Now connect the outgoing disc (top right) of that modifier with the ingoing disc (top left) of the "show by path" modifier. We now created a rule that says post shows only, "if the current path starts with 'posts' AND is 2 levels deep ".

We can now already almost start writing our blog posts. Just click on "posts" in the menu and add more posts via the "create new node" widget.

Access nodes, content and text from within the presenter class

One thing to fix in our post-presenter-class is the "showDate" method. The way we created it, it will always show the current time. For our blog posts it would be great to show the time of the creation of the post.

ff stores that information by default as a property of the node. From within a presenter class, we can access the whole site structure and also the node we're currently looking at. the current node is an object of type "ffNode" and is accessible via the property "me" (this>me->get('name of property') will give us the value of that property. ff stores the creation date of a node in a property named "date" in the unix timestamp format. To fix our code we can change it like this:

<?php class post extends ffPresenter{ public function showDate(){ $date = $this->me->get('date'); return DateTime::createFromFormat('U', $date)->format('Y-m-d H:i:s'); } }

Now every blog post shows its creation time.

Iteration

Thanks to the ffMenu presenter we have a menu to navigate to the different post nodes.
But now we want to create our own component, that also allows us to preview the blog posts. We will call it posts.

First, we'll create the template to define look and structure.

File system/plugins/myPlugin/presenter/posts.html:

<nav> <ul data-ffIterate> <li class="post-preview"> <a href=""> <h3 data-ffText='{"section":"title", "edit":false}'></h3> <figure data-ffMedia='{"width":180, "height":180}'></figure> </a> </li> </ul> </nav>

Let's quickly create a bare bone styling for the posts preview:

File system/plugins/myPlugin/css/posts.css:

.posts{ .post-preview{ display:inline-block; margin:1em; } }

In the Draftboard panel, position the posts presenter above the post presenter.

The attribute data-ffIterate, that we added to the ul element sets the base for our iteration.
By default, it iterates over the child nodes of the node that relates to the currently browsed path and repeats its child DOM element scoped to each of those nodes.
This means, that if you browse to posts, the presenter will show as many <li> elements as there are child nodes of posts. Each <li> will be scoped to its node.

Therefore, in the browser preview you should now see names and media of the child nodes of the currently browsed path.

See the chapter Iterating in the Templating section to learn much more about the use of data-ffIterate in DOM Templating.

We want our posts presenter to be visible only when the user navigates to the posts node, so again use a showByPath modifier, set its property is to the value posts and connect it with our posts presenter.

The last missing piece of our posts presenter is the href attribute that should link to the post node.

We can use data-ffLink for that purpose. By default, it simply injects the correct href that navigates to the current node, which in our snippet is the child node of posts in each iteration.

By adding data-ffLink to the <a> element, we link each post preview to its post:

File system/plugins/myPlugin/presenter/posts.html:

[...] <a href="" data-ffLink> [...]

See the chapter Navigation and Hyperlinks in the Templating section to learn much more about the use of data-ffLink in DOM Templating.

Editing structure

We now have a minimal setup for a blog. We now want to enhance it with authoring tools to create, manage and delete blog posts.

Accessing text and media from the presenter class

We remain in the backend to get familiar with more of its fundamental components.

The ffNode class has two often used properties:

  • ffNode::babel to access a node's text. It points to the ffBabelfish class.

  • ffNode::content to access a node's content, such as media or files. It points to the ffContent class.

In order to access the 'name' section of our node's text, we can write $this->me->babel->section('name') Same way, to access the node's media we can write $this->me->content->getThumbs(). This would give us an array of objects of type ffThumb objects that hold the media that is stored in that node. [The name thumb stems from thumbnail]. To output the thumb, there is the method ffThumb::call();

The property cascade

Metadata and Taxonomy

28 März 2024