[TUTORIAL] Build a ZOO Element

[TUTORIAL] Build a ZOO Element

Welcome to the first in a series of tutorial blogs ZOOModsPlus will be releasing over the next few months. In this tutorial we are going to learn how to build a ZOO element. Elements are the basic building blocks of the ZOO CCK and if you're serious about becoming a ZOO developer, knowing how to build a custom element is a must. In fact knowing how to develop a custom element can get you out of many tricky spots when building a ZOO powered website. The element we will build in this tutorial is called "Icon" and, although it won't be massively useful, it will give you a clear idea of how to build a basic element.

Get the code on GitHub

Step 1 - File/Folder Creation

Let's start by creating files for the element files. First create a folder called "icon" in "media/zoo/elements/" and inside create 2 files; icon.xml and icon.php.

Image 5

The XML is the file that tells ZOO about our element, and the PHP file is the file that contains all our business logic.

Step 2 - Barebones Code

In the XML we’re simply going to give the element a name, some copyright information and a description. The XML is where we will define the configuration parameters for our element, but we’ll come back to this in step 7.

In the XML add your data:

<?xml version="1.0" encoding="utf-8"?>
<element type="icon" group="ZMP">
<name>Icon</name>
<author>Ray Lawlor</author>
<creationDate>October 2018</creationDate>
<copyright>Copyright (C) Ray Lawlor - ZooModsPlus.com</copyright>
<authorEmail>zoomodsplus@gmail.com</authorEmail>
<authorUrl>https://www.zoomodsplus.com</authorUrl>
<version>1.0.0</version>
<description>Icon Element For Tutorial</description>
<params>
</params>
<params group="render">
</params>
</element> 

So now we have the XML defined, let’s set up the barebones basic element PHP code. This should be just enough to get our ZOO app to recognise that we have a new element. 

Add this basic PHP class to the PHP file:

<?php

// no direct access
defined('_JEXEC') or die('Restricted access');

class ElementIcon extends Element implements iSubmittable {

public function hasValue() {
return true;
}

public function render() {
return "Hello World!";
}

public function edit() {
return false;
}

public function renderSubmission($params = array()) {
return false;
}

public function validateSubmission($value, $params) {
return true;
}

}

At this point you will see that the emement is now available in the backend and you can drop the new element into a layout and see the "Hello World" text being rendered to the frontend.

  • Lesson - The "element" methods

    Lesson - The "element" methods

    The hasValue method
     public function hasValue() {
    return true;
    }

    This method tells ZOO if the element has any value and whether is should render in the frontend. Remember, ZOO layout positions don’t show if the elements inside that position have no value. This method needs to return ‘true’ for the element to show in the frontend. we can use use any PHP logic to determine if the value is set so this simple method is extremely powerful as we'll see in future tutorials.

    The render method
     public function render()
        {
            return "Hello World!";
        }

    This is what gets rendered in the frontend. We return a string here which can contain any HTML markup you need for the frontend view.

    The edit method
      public function edit()
        {
            return false;
        }

    This is where we set the backend form.

    The renderSubmission method
    public function renderSubmission($params = array())
        {
            return false;
        }

    This method renders the frontend submission form field. Yes ZOO allows us to render the backend form field in a different way to the frontend form field.

    The validateSubmission method
    public function validateSubmission($value, $params)
        {
            return true;
        }

    This method allows us to make sure that frontend submitted data is valid.

Step 3 - Setting the backend field

Now that we have a working element we can begin making it useful. In order to demonstrate how the backend field is set up, first we're going to set up a simple text field then we're going to change it to a dropdown select list that will allow a user to select a UIkit icon.

Change the edit method to:

public function edit()
    {
        return $this->app->html->_('control.text', $this->getControlname('value'), $this->get('value'), 'size="60" title="'.JText::_('Icon').'"');
    }

This code calls the 'underscore' function from the HTML helpers from within the ZOO system. This function takes 4 arguments, the first is the type of field you want to render, in this case it’s text, so we enter 'control.text'. The next 3 arguments are, the name of the field, the value of the field, the next last is a string that describes the typical field attributes. 

In the NAME argument, we need to call another ZOO property. This code specifies the name of field. So we use getControlName to set the name of the field. ZOO will remember this "key" value and allow us to call the value later when we render. In the value argument, we use "get" and we use the 'key' we used in the control. In fact we can use the 'get' method anywhere in the element code to get that stored value.

If you take a look at the backend item edit, you'll see our text field. To test, enter a value and save the item. The element will save the value, but you'll notice that the frontend view doesn't change, this is becuase we now need to change the render method to show the saved value.

Image 4

Step 4 - Setting the render to show the saved value

Change the render method to:

public function render()
    {
        return $this->get('value');
    }

This simply grabs the saved value using the 'get' method. The 'value' key here mush match with whatever value you gave getControlName in the edit method, in this case it's 'value'.

Now look at the frontend and you'll see the element will render out whatever value you gave the field in the backend.

Step 5 - Advanced backend fields

We can now do a little bit more with the backend editing. Rather than this simple text field in the backend, let’s have a drop down select box with a few of the Uikit icons for our user to choose from.

Change the edit method to:

public function edit()
    {
        $options = array(
// '[VALUE]' => '[TEXT]' 'home' => "Home", 'user' => "User", 'image' => "Image", 'heart' => "Heart", 'mail' => "Mail", ); return $this->app->html->_('select.genericlist', $options, $this->getControlName('value'), null, 'value', 'text', $this->get('value')); }

Here we've set up an associative array called $options. These are the values we want in the dropdown. We then change the 'underscore' method to 'select.genericlist' and then the second argument is the options array, we then set the usual control name and values.

Image 2

Looking at the backend form you'll see we now have a select list with the vlaues we specified in the options array.

Step 6 - Getting the icon to show in the frontend. 

Now that we have set the value using the dropdown, we can now ajust the code in the render method to show the icon.

Change the render method to:

public function render()
    {
       $value = $this->get('value');

       return '<span uk-icon="icon: '. $value .'"></span>';
    }

 Now look at the frontend item and you will see whatever icon you've chosen. 
**NOTE: this assumes you're already loading Uikit 3

Image 3

STEP 7 - Creating Parameters 

Let's give our element the abilty to change the size of the icon via the backend parameters. We set our parameters in the XML manifest.

There are 2 sets of params on any given element, one is the main element params and the other is the render params. The main params are the ones you set when you first create the element in the backend. The render params are the params that are controlled inside the layout settings.

Since we’re setting the size which is a visual parameter, so let’s control that via the render params.

Change the XML code to: 

<?xml version="1.0" encoding="utf-8"?>
<element type="icon" group="ZMP">
<name>Icon</name>
<author>Ray Lawlor</author>
<creationDate>October 2018</creationDate>
<copyright>Copyright (C) Ray Lawlor - ZooModsPlus.com</copyright>
<authorEmail>zoomodsplus@gmail.com<;/authorEmail>
<authorUrl>https://www.zoomodsplus.com</authorUrl>
<version>1.0.0</version>
<description>Icon Element For Tutorial</description>
<params>
</params>
<params group="render">
<param>
<option value="1">Default</option>
<option value="2">Large</option>
<option value="3">X Large</option>
</param>
</params>
</element> 

Now look at the layout settings for the element, and you'll see we now have a dropdown with the options we've specified. 

Image 1

Step 8 - Feeding parameters to the frontend view

Ok now that we have some options, we need to feed the values back into the render method if you want to use them in the frontend view.

Change the render method to:

 public function render($params = array())
    {
       $params = $this->app->data->create($params);
       
$size = $params->get('size);
$value = $this->get('value'); return '<span uk-icon="icon: '. $value .'; ratio: '. $size .'"></span>'; }

Here we have called the the params in via the method argument then initialised them via the "create" method on the "data" helper. We can then access any param via the param name on the "get" method. We then adjust the markup to include the ratio of the icon.

Step 9 - hasValue Housekeepoing 

We need to put some logic into our hasValue method to make sure our element has a value before rendering. This is a simple bit of logic. Simply return the value stored via the "get" method. This get function will return false if there is no value stored and return true when we have a value.

 Change the hasValue method to:

 public function hasValue($params = array())
    {
       return $this->get('value');
    }

Step 10 - Using the render template system 

Right now the render method returns the HTML directly. For a simple element like our icon element, this is usually OK. But for larger more complex elements, you’re going to want to bring your markup into a separate template file and then tell the render method where to go get your frontend markup.

First let’s create a folder named "tmpl" and inside this we create a PHP file named render.php.

Image

In the tmpl/render.php file put:

<?php 

// no direct access
defines('_JEXEC') or die('Restricted Access');

?>

<span uk-icon="icon: <?php echo $value; ?>; ratio: <?php echo $size; ?>"></span>

Now we can tell our render method to go get the template. Do do this we use the renderLayout function. This function takes two arguments, one is the layout filename and the other is an array of variables we send into the view. It’s good practice to wrap this in an if block and test to see if the layout file is present.

Change the render method to:

public function render($params = array())
    {

        $params = $this->app->data->create($params);

        if ($layout = $this->getLayout('render.php')) {
            return $this->renderLayout($layout, array(
                'size' => $params->get('size'),
                'value' => $this->get('value')
            ));
        }

    }

The second argument in the renderLayout function is extremely powerful as we can use private functions within our class to manipulate variables before loading the template. That’s a bit advanced for this video but I will cover this at another time.

Note: we can also do some cool customisations on the backend edit view, by doing the same with the edit method. Simply make the same changes within the edit method, and call in edit.php file from the tmpl folder.

 

Leave a comment

You are commenting as guest.

Get updates in your inbox:

Copyright © 2018 ZooModsPlus.
ALL RIGHTS RESERVED.