TodoMVC with WordPress and intercooler.js 02

A first intercooler.js and WordPress interaction.

Todo post type

Aside for some code refactoring I’ve done little beside adding a first route and handler in the version of the theme current to this post.
As a first step, in the function/post-type.php file, I’m registering a new post type and relevant stati

add_action( 'init', function () {
    register_post_type( 'todo' );
    register_post_status( 'active' );
    register_post_status( 'completed' );
} );

Markup modifications

The second step is a small modification of the HTML to allow me to use intercooler.js and its attributes.
The relevant parts are those in the part of the index that’s in charge of rendering the todo list

<section class="todoapp">
<header class="header">
    <input class="new-todo" placeholder="What needs to be done?" autofocus="" ic-post-to="/tasks" name="task-title"
<div id="todo-list">
    <?php todomvc_the_list() ?>

Since I will re-render the list when a new todo is added I’ve delegated the todomvc_the_list function the task to render the list initial state.
Defined in the functions/output.php file it’s just a rewriting of the static markup to allow for PHP-driven dynamics to kick in

function todomvc_the_list( $status = [ 'active', 'completed' ] ) {
    $todos = get_posts( [
        'post_type'   => 'task',
        'post_status' => $status,
        'nopaging'    => true
    ] );
    <section class="main">
        <input class="toggle-all" type="checkbox">
        <label for="toggle-all">Mark all as complete</label>
        <ul class="todo-list">
            <?php foreach ( $todos as $todo ): ?>
                <?php $status = $todo->post_status == '' ? '' : 'class = "completed"'; ?>
                <li <?php echo $status ?>>
                    <div class="view">
                        <input class="toggle" type="checkbox">
                        <label><?php echo $todo->post_title ?></label>
                        <button class="destroy"></button>
                    <input class="edit" value="<?php echo $todo->post_title ?>">
            <?php endforeach; ?>
    <footer class="footer">
        <span class="todo-count"><strong>1</strong> item left</span>
        <ul class="filters">
                <a class="selected" href="#/">All</a>
                <a href="#/active">Active</a>
                <a href="#/completed">Completed</a>

        <button class="clear-completed">Clear completed</button>

A first objective

From the code of the function above it’s clear I’m outputting fixed numbers and strings in a lot of places where dynamic values should show and any form of security is missing.
That’s intentional: I will add the required functions in small steps and will worry about one at a time.
The first step is being able to add todos to the list.

intercooler.js attributes

In the index.php file I’ve modified the input used to insert a new todo to this

        <input class="new-todo" 
        placeholder="What needs to be done?"

Beside the usual attributes what’s relevant is: 1. I’ve added the name attribute: intercooler.js will not send along data if the input has no name 2. the ic-post-to attribute tells intercooler.js to make a POST request to the /tasks path when the user presses Enter 3. the ic-target attribute, a valid jQuery selector, tells intercooler.js to replace the HTML code of the list with the new returned content

A first route

Point 2 of the list above specifies a /tasks path as the destination of the POST request.
Since I’m using the wp-routes plugin to handle the routing I’ve defined that route in the functions/routes.php file

add_action( 'wp-routes/register_routes', function () {
    // Add a new todo
    respond( 'POST', '/tasks', function ( $request, $response ) {
        if ( empty( $_REQUEST['task-title'] ) ) {
        $id = wp_insert_post( [
            'post_title'  => $_REQUEST['task-title'],
            'post_type'   => 'task',
            'post_status' => 'active'
        ] );

        if ( empty( $id ) ) {
        $response->header( 'X-IC-Trigger', 'todomvc/new-task-added' );
    } );
} );

In the function handling the route I’m inserting a new active todo in the database and re-rendering the list.
intercooler.js will use any output I return to replace the list or will do nothing if nothing echoes back.

Clean the input

After a todo insertion I will clean the input using an event handler specified in the assets/js/todomvc.js file

/*global jQuery:false */
jQuery( document ).ready( function ( $ ) {
    'use strict';

    $( 'body' ).on( 'todomvc/new-task-added', function () {
        $( 'input[name="task-title"]' ).val( '' );
    } );
} );

The event that’s triggering the input cleaning is the todomvc/new-task-added one.
Looking at the code above I’m triggering that event in the X-IC-Trigger header that I’m returning.
Caveat: intercooler.js seems to trigger the events specified in the X-IC-Trigger header on the body element of the document; that makes sense thinking about events triggered this way as global events but might not be the best course of action in more complicated applications.


I will add the possibility to mark a todo as complete next.