Oh hey look, View Models

Writificated on February 5th, 2019

Have ever had some complex data or conditions you found challenging to work with in your Antlers templates? Sure you have. Have you ever peeled a banana and had the stem hang onto the peel stubbornly only to have the fruit poke it's face out like it's wearing a hoodie? You know you can relate to that too.

While Antlers is powerful and flexible, what if you could just jump into PHP-land, work out some tricky logic, and put the data back in place before it was rendered?

Enough rhetorical questions – in Statamic 3 you can now solve one of those two problems with a View Model. 🍌

View Models in Action

By defining a view_model in your entry data (or anywhere in the cascade), Statamic will run the data() method of that named class and will merge any array data you return in it before injecting it into your view/template. Inside the view model you will have access to the full cascade and can set new variables or modify existing ones.

Time for an example. Let's assume we have a Replicator field with a lot of content blocks (an associative array) and we'd like to calculate some stats on how much content there is and how long it might take to read it.

You could probably do this with modifiers, but the templating would likely get pretty complicated to read and make future-you (or another developer) a little mad.

First, we'll define the view model location.

title: "A Long Article Plz Read it Mmmkay?"
view_model: App\ViewModels\ArticleStats
content:
  -
    type: text
    text: # Piles of content live here

Next, we'll loop through the content, assemble a giant string of all the content, run a few math functions, and return the stats.

<?php

namespace App\ViewModels;

use Statamic\View\ViewModel;

class ArticleStats extends ViewModel
{
    public function data(): array
    {
        // Combine content blocks
        $html = collect($this->cascade->get('content'))
                ->implode('text', " ");

        // Remove HTML tags
        $content = strip_tags($html);

        // Calculate stats
        $character_count = strlen($content);
        $word_count      = mb_str_word_count($content);
        $read_time       = ceil($word_count / 200);

        return [
            'character_count' => $character_count,
            'word_count'      => $word_count,
            'read_time'       => $read_time
        ];
    }
}

Finally, we'll show these stats in our view.

<h1>{{ title }}</h1>
<p class="meta">
    {{ word_count}} words / read time approx {{ read_time }}m.
</p>

View models help keep your views nice and clean. Use them early and often, they're going to be your new best friend. Just keep in mind, you're manipulating the view's data at the last possible moment before render, not the Entry data itself. This approach isn't appropriate for globally altering or manipulating your content everywhere and anywhere you may access it.

Stay tuned for more updates on Statamic 3 later this week!

Jack McDade
Jack McDade, Creator of Statamic
Creator of Statamic

Copyright 2019 Statamic