Categories
Tutorial

Can You Have Markdown in the CakePHP Form Helper?

It’s no secret that the default HTML toolkit is pretty lackluster, at least compared to the plethora of hand-holding tools offered to the average MS Office user nowadays. Make your users feel more at home by adding markdown to your textareas, you could also check out my guide on how to use voice input. With Quilljs’s markdown, you can add images inline, create bulleted lists, and, more importantly, you can turn off those features at will. While you can add a script at the bottom of certain pages that contain textareas I wanted to create a less hacky solution, so in this tutorial, I’ll show you how to alter the Form Helper’s default textarea!

Adding Quilljs to Our Application

Before we alter any templates we’ll need to add Quill to our application. In your default header layout add the following libraries.

<html>
  <head>
    <!-- ... -->
    <link href="<https://cdn.quilljs.com/1.3.6/quill.snow.css>" rel="stylesheet">
    <script src="<https://cdn.quilljs.com/1.3.6/quill.js>"></script>
    <!-- ... -->
  </head>
</html>

This will allow you to use inputs that have markdown like this:

<div id="editor-container">
</div>
<script>
var quill = new Quill('#editor-container', {
  modules: {
    toolbar: [
      [{ header: [1, 2, false] }],
      ['bold', 'italic', 'underline'],
      ['image', 'code-block']
    ]
  },
  placeholder: 'Compose an epic...',
  theme: 'snow'  // or 'bubble'
});
</script>
Wow, so cool 😎

Now we have a working markdown input πŸ₯³! How do we make it more reusable πŸ€”? We don’t want to add a script tag after every textarea, that would be lame! Let’s look at how to generalize our script.

Updating Quill Initializer

In order to support multiple textareas on the same page, each will have to have a unique identifier. We’ll also have to include a hidden field to store the markdown written in the Quilljs box since, as we saw earlier, the input is an editable div, not an input. To accomplish this we will include a script in our default footer layout.

src/Template/Layout/default.ctp (or wherever you have your footer)

  <!-- ... -->
  </body>
  <footer>
    <!-- ... -->
    <script>
      //Quill editor (markdown)
      if($('.editor').length) {
        var form = $('form');
        var quill = {};
        if(form.has('.editor').length) {
          $('.editor').each(function(){
            var name = $(this).attr('data-name');
	
            quill[name] = new Quill('.editor-' + name, {
                                        theme: 'snow'
		                      });
		
            form.submit(function(event) {
              // Populate hidden form on submit
              var input = $('input[name="'+ name +'"]');
              input.val(quill[name].root.innerHTML.trim());
            });
          });
        }
      }
    </script>
  </footer>
</html>

Our script does two things

  1. Initializes every element with a class of editor as a Quilljs input.
  2. When a form is submitted that contains Quilljs inputs we populate a hidden input field with the data.

Now our application is ready to have its textarea template rewritten!

Altering Our Textarea Template

If you don’t already have the form helper active in your application you can activate it in the AppView.php

<?php
namespace App\View;

use Cake\View\View;

class AppView extends View {
  public function initialize() {
    parent::initialize();
    $this->loadHelper('Paginator', ['templates' => 'paginator-template']);
    $this->loadHelper('Form', [
      'templates' => 'app_form'
    ]);
  }
}
?>

The paginator helper isn’t necessary for this, but it would help if you were trying to do a real-time paginated search with AJAX.

You can also see that we define a template in 'app_form' . Create a new file in your config file called app_form.php and add this updated textarea template.

return [
    'textarea' => '<div class="form-group"><input name="{{name}}" type="hidden"><div class="editor editor-{{name}}" data-name="{{name}}">{{value}}</div></div>',
];

The HTML looks like this:

<div class="form-group">
  <input name="{{name}}" type="hidden">
  <div class="editor editor-{{name}}" data-name="{{name}}">
    {{value}}
  </div>
</div>

We’ve included the default variables in the original textarea template in order to still display the stored data and name the input correctly.

If you don’t currently use the form helper to generate textareas you can use the following template.

<div class="form-group">
  <input name="{attribute-name}" type="hidden">
  <div class="editor editor-{attribute-name}" data-name="{attribute-name}">
    <?= $recordVariable->{attribute-name} ?>
  </div>
</div>

Where {attribute-name} is to be replaced by your $recordVariable‘s attribute name.

Now whenever you do create a textarea using the form helper:

$this->Form->textarea('varname');

You’ll get a Quilljs markdown editor!

Conclusion

Now you have much nicer looking textareas! Congratulations by the way πŸŽ‰.

Have an issue with the tutorial, want me to write about your issue, think emojis should be used as more expressive punctuation marks❔ Let me know in the comments below!

Don’t forget to subscribe for more tutorials every Tuesday, and a bonus Thursday thoughts post!

See you next week 😁!