Components

Components are reusable chunks of code and markup, comprised of a component class and optional component view(s). Like partials, but with the ability to process arguments and provide callable methods.

Wireframe components are classes that extend the \Wireframe\Component base class. They can either render output directly by implementing a render() method, or they can rely on a separate Component View file for markup generation.

Component support was added in Wireframe 0.8.0.

When should I use components instead of partials?

Components and partials are used for similar reason: when you need reusable blocks of markup. Regardless, there's one major difference between the two, and that is the class file that components build on.

If you need to pass that reusable block of code parameters, process said parameters in, or perhaps fetch data dynamically – say, from an API of some sort – then you most likely want a component. On the other hand if you just need to reuse a bit of markup with minimal logic in it (simple if and foreach structures at most), a partial is often quite enough.

Partials are – by design, mind you – plain PHP files with no clean way to process arguments or separate code from markup. If you have a static snippet that you'd like to embed into your views or layouts repeatedly, partials are your best friend.

Components, on the other hand, provide extra layer where you can specify valid params, process said params, and include any additional "business logic".

Component views

The number of views each component has can vary: some may have none, while others can have dozens. Unless you override the render() method in your component class, the implementation inherited from the base class will automatically attempt to render the component using a default view file at /site/templates/components/ComponentName/default.php.

Note that the path to the components directory (by default /site/templates/components/) is configurable.

You can override the default view file in your component class, or from outside of it, by calling Component::setView($view), where $view is the name of the view file without the .php extension. This is useful if, for an example, your component should be rendered in a completely different way depending on the parameters that were passed to it.

In some cases it may not be necessary to have a separate view file at all. A component returning markup directly from the render() method is a perfectly valid as well. For an example you could have a component that grabs a Markup module and in the component's render method calls the render method of said module and returns resulting markup.

Accessing Component class from component view

Added in Wireframe 0.26.0.

In most cases you can — and should — pass data from the Component class to the view, or call Component class methods with syntax such as $this->method_name, but if you do require direct access to the Component class from component view, as of Wireframe 0.26.0 it has been made possible via ComponentView::getComponent():

<?php namespace ProcessWire; ?>

<p>
Hey <?= $this->getComponent()->formatName($input->get->name) ?>.
How you doing?
</p>

Methods of the Component class

Public methods provided by the Component base class:

Additional static helper method provided by the Wireframe module:

Examples

Here's a simplified example of how this comes together:

/site/templates/components/Card.php (class for the Card component)

<?php

namespace Wireframe\Component;

/**
 * Card component
 */
class Card extends \Wireframe\Component {

    /**
     * Constructor method
     *
     * @param \ProcessWire\Page $item Page related to current Card.
     * @param string|null $title Optional card title, overrides page title.
     * @param string|null $summary Optional card summary, overrides page summary.
     */
    public function __construct(\ProcessWire\Page $item, ?string $title = null, ?string $summary = null) {

        // Pass properties to view
        $this->title = $title ?: $item->title;
        $this->summary = $summary ?: $item->summary;
        $this->image = $item->get('image|hero_image');
    }

}

/site/templates/components/Card/default.php (default view for the Card component)

<?php namespace ProcessWire; ?>
<div class="card">

    <?php if ($image): ?>
        <img src="<?= $image->size(640, 480)->url ?>" alt="<?= $image->description ?>">
    <?php endif; ?>

    <h3><?= $title ?></h3>

    <?php if ($summary): ?>
        <p><?= $summary ?></p>
    <?php endif; ?>

</div>

... and for fetching and rendering the component in one of our views or layouts – or components for that matter – we can use the static helper method included in the Wireframe module class:

<?php foreach ($cards as $item): ?>
    <?= Wireframe::component('Card', [$item]) ?>
<?php endforeach; ?>

If your component takes multiple arguments, you can (as of Wireframe 0.12.0) specify the names via an assoc array:

<?php foreach ($cards as $item): ?>
    <?= Wireframe::component('Card', [
        'item' => $item,
        'summary' => 'Look mum, we skipped the title!',
    ]) ?>
<?php endforeach; ?>

Note that Wireframe::component($component_name, $args) actually returns an instance of the component class instead of a string, but since internally Component::__toString() calls Component::render(), what we're doing here is essentially the same as echoing out the result of (new \Wireframe\Component\Card($item))->render().

Back to top