Flag of Ukraine
SymfonyCasts stands united with the people of Ukraine

Clearing the Form, Prepping for a Template

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 $12.00

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

Login Subscribe

Let's do the easy thing first: when we submit the form successfully, these errors need to disappear!

We already have code for that, so copy it, and isolate it into its own new method called _removeFormErrors:

... lines 1 - 2
(function(window, $) {
... lines 4 - 24
$.extend(window.RepLogApp.prototype, {
... lines 26 - 107
_removeFormErrors: function() {
var $form = this.$wrapper.find(this._selectors.newRepForm);
$form.find('.js-field-error').remove();
$form.find('.form-group').removeClass('has-error');
},
... lines 113 - 119
});
... lines 121 - 138
})(window, jQuery);

Call that from our map function:

... lines 1 - 2
(function(window, $) {
... lines 4 - 24
$.extend(window.RepLogApp.prototype, {
... lines 26 - 88
_mapErrorsToForm: function(errorData) {
this._removeFormErrors();
var $form = this.$wrapper.find(this._selectors.newRepForm);
... lines 92 - 105
},
... lines 107 - 119
});
... lines 121 - 138
})(window, jQuery);

The other thing we should do is empty, or reset the fields after submit. Let's create another function that does that and removes the form's errors. Call it _clearForm. First call this._removeFormErrors():

... lines 1 - 2
(function(window, $) {
... lines 4 - 24
$.extend(window.RepLogApp.prototype, {
... lines 26 - 113
_clearForm: function() {
this._removeFormErrors();
... lines 116 - 118
}
});
... lines 121 - 138
})(window, jQuery);

To "reset" the form, get the DOM Element itself - there will be only one - by using [0] and calling reset() on it:

... lines 1 - 2
(function(window, $) {
... lines 4 - 24
$.extend(window.RepLogApp.prototype, {
... lines 26 - 113
_clearForm: function() {
this._removeFormErrors();
var $form = this.$wrapper.find(this._selectors.newRepForm);
$form[0].reset();
}
});
... lines 121 - 138
})(window, jQuery);

I love that this [0] thing isn't a mystery anymore!

Call this from up in success: self._clearForm():

... lines 1 - 2
(function(window, $) {
... lines 4 - 24
$.extend(window.RepLogApp.prototype, {
... lines 26 - 65
handleNewFormSubmit: function(e) {
... lines 67 - 74
$.ajax({
... lines 76 - 78
success: function(data) {
self._clearForm();
},
... lines 82 - 85
});
},
... lines 88 - 119
});
... lines 121 - 138
})(window, jQuery);

Ok, test this baby out! Submit it empty, then fill it out for real and submit. Boom!

Client-Side Templating??

Ok, back to the main task: on success, we need to add a new row to the table. We could do this the easy way: by manually parsing the JSON and building the table. But there's one big problem: I do not want to duplicate the row markup in Twig AND in JavaScript. Instead, we're going to use client-side templates.

Let's start off simple: at the bottom of our object, add a new function: _addRow that has a repLog argument. For now just log that: this will be the RepLog data that the AJAX call sends back:

... lines 1 - 2
(function(window, $) {
... lines 4 - 24
$.extend(window.RepLogApp.prototype, {
... lines 26 - 121
_addRow: function(repLog) {
console.log(repLog);
}
});
... lines 126 - 143
})(window, jQuery);

Call this from up in the success callback: self._addRow(data):

... lines 1 - 2
(function(window, $) {
... lines 4 - 24
$.extend(window.RepLogApp.prototype, {
... lines 26 - 65
handleNewFormSubmit: function(e) {
... lines 67 - 74
$.ajax({
... lines 76 - 78
success: function(data) {
self._clearForm();
self._addRow(data);
},
... lines 83 - 86
});
},
... lines 89 - 124
});
... lines 126 - 143
})(window, jQuery);

Let's make sure things are working so far: refresh and add a new element. Yes! The data has id, itemLabel and even a links key with a URL for this RepLog. We are ready to template!

In a nutshell, a client-side, or JavaScript templating engine is like having Twig, but in JavaScript. There are a lot of different JavaScript templating libraries, but they all work the same: write a template - a mixture of HTML and dynamic code - and then render it, passing in variables that are used inside. Again, it's just like using Twig... but in JavaScript!

One simple templating engine comes from a library called Underscore.js. This is basically a bunch of nice, utility functions for arrays, strings and other things. It also happens to have a templating engine.

Google for Underscore CDN so we can be lazy and include it externally. Copy the minified version and then go back and open app/Resources/views/base.html.twig. Add the new script tag at the bottom:

... lines 1 - 90
{% block javascripts %}
... lines 92 - 93
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.8.3/underscore-min.js"></script>
{% endblock %}
... lines 96 - 99

Now, let's start templating!

Leave a comment!

0
Login or Register to join the conversation
Cat in space

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

This tutorial uses an older version of Symfony... but since it's a JavaScript tutorial, the concepts are still ? valid!

What PHP libraries does this tutorial use?

// composer.json
{
    "require": {
        "php": "^7.2.0",
        "symfony/symfony": "3.1.*", // v3.1.10
        "twig/twig": "2.10.*", // v2.10.0
        "doctrine/orm": "^2.5", // v2.7.1
        "doctrine/doctrine-bundle": "^1.6", // 1.10.3
        "doctrine/doctrine-cache-bundle": "^1.2", // 1.3.2
        "symfony/swiftmailer-bundle": "^2.3", // v2.4.0
        "symfony/monolog-bundle": "^2.8", // 2.12.0
        "symfony/polyfill-apcu": "^1.0", // v1.2.0
        "sensio/distribution-bundle": "^5.0", // v5.0.22
        "sensio/framework-extra-bundle": "^3.0.2", // v3.0.16
        "incenteev/composer-parameter-handler": "^2.0", // v2.1.2
        "friendsofsymfony/user-bundle": "~2.0@dev", // dev-master
        "doctrine/doctrine-fixtures-bundle": "~2.3", // v2.4.1
        "doctrine/doctrine-migrations-bundle": "^1.2", // v1.2.1
        "composer/package-versions-deprecated": "^1.11", // 1.11.99
        "friendsofsymfony/jsrouting-bundle": "^1.6" // 1.6.0
    },
    "require-dev": {
        "sensio/generator-bundle": "^3.0", // v3.1.1
        "symfony/phpunit-bridge": "^3.0" // v3.1.6
    }
}
userVoice