Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine
This tutorial has a new version, check it out!

Custom Fields with JavaScript

Keep on Learning!

If you liked what you've learned so far, dive in!
Subscribe to get access to this tutorial plus
video, code and script downloads.

Start your All-Access Pass
Buy just this tutorial for $8.00

With a Subscription, click any sentence in the script to jump to that part of the video!

Login Subscribe

99% of stuff in EasyAdminBundle is really easy. But it's that last, pesky 1% that can be so tough! And usually, that last 1% involves a form.

Sometimes, you have a form field that needs to be really customized. Maybe you need to write a bunch of special JavaScript, your own HTML or even create some custom routes and make AJAX calls back to them. Well... so far, all we can do is... just use the built-in form field types. And while that system is super extensible, it can also be super complex. So, we're going to dive into two examples where we do something very custom, without pulling our hair out.

Adding the JS Markdown Field

On the front-end of our site, this funFact field is processed through Markdown. That means we can totally use Markdown syntax inside its textarea. But... our admin users aren't very comfortable with Markdown... and being the awesome programmers that we are, we want to help them! I want to embed a JavaScript markdown previewer library called Snarkdown. You type some markdown, and Snarkdown shows you a preview.

So how can we transform our boring textarea field to include this?

In config.yml, under Genus, find the funFact field and add a css_class option set to js-markdown-input:

... lines 1 - 80
... lines 82 - 94
... lines 97 - 117
... lines 120 - 124
- { property: 'funFact', type: 'textarea', css_class: 'js-markdown-input' }
... lines 126 - 148

This will be our new best friend. Because now that the element has this CSS class, we can write JavaScript to do whatever insane crazy things we want!

How do we include JavaScript on the page? We already know how! Up at the top, under design and assets, add js. Let's add 2 JavaScript files. First, include the Snarkdown library:

... lines 1 - 80
... line 82
... line 84
... line 86
- 'https://unpkg.com/snarkdown@1.2.2/dist/snarkdown.umd.js'
... lines 89 - 148

We could also download it locally. And include a new js/custom_backend.js file:

... lines 1 - 80
... line 82
... line 84
... line 86
- 'https://unpkg.com/snarkdown@1.2.2/dist/snarkdown.umd.js'
- 'js/custom_backend.js'
... lines 90 - 148

To save some time, if you downloaded the code that came with this tutorial, you'll have a tutorial/ directory with a custom_backend.js file inside. Copy that, go into web/js and paste:

$(document).ready(function () {
var $markdownInputs = $('.js-markdown-input .form-control')
$markdownInputs.after('<div class="markdown-preview"></div>');
$markdownInputs.on('keyup', function (e) {
var html = snarkdown(e.target.value);
e.target.nextElementSibling.innerHTML = html;

It's pretty simple: inside a $(document).ready() block, it finds all the js-markdown-input classes, gets their .form-control element, adds a new markdown-preview div and then processes that through Snarkdown. Basically, it creates an element that will show the preview version of our Markdown.

In that same tutorial/ directory, there's also a custom_backend.css file. Just copy its contents. Open our custom_backend.css file and paste at the bottom... to make things just a little prettier:

... lines 1 - 4
.markdown-preview {
margin-top: 10px;
border: 2px dashed #da3735;
padding: 5px;
.markdown-preview::before {
content: "Preview: ";

I think we're ready! Refresh the page. Bam! There's our preview below the field. We can add some bold... and use some ticks. We rock!

I want you to realize how powerful this is. You can easily add a css class to any field. And then, by writing JavaScript, you can do anything you want! You could render a text field, hide it and then entirely replace the area with some crazy, custom JavaScript widget that updates the hidden text field in the background. This is your Swiss Army Knife.

In fact, we're going to do something similar next.

Leave a comment!

Login or Register to join the conversation
Cat in space

"Houston: no signs of life"
Start the conversation!

This tutorial is built on an older version of Symfony & EasyAdminBundle. Many of the concepts are the same, but you can expect major differences in newer versions.

What PHP libraries does this tutorial use?

// composer.json
    "require": {
        "php": ">=5.5.9",
        "symfony/symfony": "3.3.*", // v3.3.18
        "doctrine/orm": "^2.5", // v2.7.2
        "doctrine/doctrine-bundle": "^1.6", // 1.10.3
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.5
        "symfony/swiftmailer-bundle": "^2.3", // v2.6.7
        "symfony/monolog-bundle": "^2.8", // v2.12.1
        "symfony/polyfill-apcu": "^1.0", // v1.17.0
        "sensio/distribution-bundle": "^5.0", // v5.0.25
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.29
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.4
        "knplabs/knp-markdown-bundle": "^1.4", // 1.7.1
        "doctrine/doctrine-migrations-bundle": "^1.1", // v1.3.2
        "stof/doctrine-extensions-bundle": "^1.2", // v1.3.0
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "javiereguiluz/easyadmin-bundle": "^1.16" // v1.17.21
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.1.7
        "symfony/phpunit-bridge": "^3.0", // v3.4.40
        "nelmio/alice": "^2.1", // v2.3.5
        "doctrine/doctrine-fixtures-bundle": "^2.3" // v2.4.1