Feb 19, 2015 Tags: JQuery, Fluid, TYPO3, Javascript

Send JSON from Fluid to JQuery

How do you hand over data from the server to the Javascript of an HTML5 document? Here’s what I found out. Currently I’m talking about TYPO3 6.2, Extbase/Fluid and JQuery 1.11.2.

The Task

Let’s say we have a form in an html5 page and we want to do advanced clientside validation. And we have a matrix of possible combinations that we want to validate against.

How to we best transmit that data?

Think of this example: We want to create a form with two choices: fruit and color. The point is that what color you can choose depends on what fruit you have chosen. And the form cannot know in advance since the fruits may be different in the next run. How do we best tell the form what choices are valid?

Try this example to understand what the form is supposed to do:

Try out the form example

In our example we first have to choose the fruit: It’s either apple or pear. After that we choose the color to find the result. For apple the possible colors are green and red. And for pear they are green and yellow. As a result we get one of the outcomes sweet, sour, tasty or hard. Let’s see how we can accomplish that.

Serverside

Extbase Controller: Setup the data

(1) We first prepare a data matrix. (2) Then we convert to Json format and (3) hand the data over to a Fluid view:

<?php

// (1) define matrix
$matrix = array(
   // choice 1: fruit, choice 2: color, result
   array('apple', 'red',    'sweet'),
   array('apple', 'green',  'sour'),
   array('pear',  'yellow', 'tasty'),
   array('pear',  'green',  'hard')
);

// (2) rewrite as json
// [["apple","red","sweet"],["apple","green","sour"],
//  ["pear","yellow","tasty"],["pear","green","hard"]]
$matrixJson = json_encode($matrix);

// (3) in TYPO3 Extbase controller: assign to view
$this->view->assign('matrixJson', $matrixJson);

?>

Fluid Template: Render the Json for HTML5

Now the tricky part: What syntax is appropriate in the Fluid template? Let’s say we want to provide the data in a data attribute of an html tag. The following works for me:

<html xmlns:f="http://typo3.org/ns/TYPO3/Fluid/ViewHelpers"
      f:schemaLocation="https://fluidtypo3.org/schemas/fluid-master.xsd">

</f:form>
   <!-- (a) html -->
   <input id="abc" name="abc" data-matrix="{matrixJson}" />

   <!-- (b) tag usage of Fluid viewhelper f:form.hidden -->
   <f:form.hidden name="bcd" id="bcd"
                  additionalAttributes="{data-matrix:'{matrixJson}'}" />

   <!-- (c) inline usage of Fluid viewhelper f:form.hidden -->
   {f:form.hidden(name:"cde", id:"cde",
                  additionalAttributes:{ data-matrix:'{matrixJson}' }) }
</f:form>

Three different ways are shown:

  1. (a) We write the <input /> tag literally and Fluid only renders the data-matrix attribute
  2. (b) We use the tag notation for the f:form.hidden Fluid viewhelper which by itself contains {matrixJson} as another Fluid inline element.
  3. (c) We use inline notation for the f:form.hidden Fluid viewhelper. And again there is the nested {matrixJson} Fluid inline element.

Why does this work? The “trick” is that the rendering of {matrixJson} automatically does a htmlspecialchars() conversion including conversion of double quotes. This makes sure that <,&,>," become &lt;, &amp; &gt;, &quot;. So the Json data doesn’t interfere with normal html tag notation.

Clientside

What happens clientside? When we use JQuery some magic is happening automatically. JQuery attaches an unique key to the tag. And it reads the data of data-matrix from the input tag. JQuery automatically tries a decode from Json which is successful in our case. As a result we get the matrix as an object (a list of lists). JQuery then stores this object in a cache owned by JQuery. Schematically this looks like jQuery.cache[uniqueTagKey]['matrix'] = matrix;. From that on JQuery doesn’t touch the tag’s data attribute any more but always uses its own cache for .data() operations.

We now can easily access the Javascript matrix object:

<script type="text/javascript">
   (function ($) {
      $(document).ready(function(){
         var matrix = $('#abc').data('matrix');
         // show just one row to prove we have
         // an object: apple,red,sweet
         alert(matrix[0]);
   })}(jQuery));
</script>

Note: Due to JQuery’s magic the conversion vom Json to object has happened automatically. If JQuery doesn’t succeed with that JSONdecode it simply returns a string.

Attention: I’m just starting with Extbase & Fluid and I have no idea whether what I’m writing is a recommended way of doing it.

What do you think?

Comments

comments powered by Disqus

Previous topic

TYPO3 TypoScript Tricks

Next topic

Directory of Online Services

Tags

Archives

Languages

Recent Posts

This Page