Extending Mustache usage in Pharo Smalltalk 
Tags: smalltalk, pharo, mustache, tutorial
Published: 2019-09-06 11:32:39

Mustache is a template system with wide variety of implementations. One of those is in Pharo Smalltalk, which will be focused on in this article. You can find out more about it [here](https://github.com/noha/mustache). 

First thing you'll notice when you open [mustache.github.io](https://mustache.github.io) is Logic-less templates, and it should remain that way. However often you want to extend the usage of one such template system and adjust it to your own needs.

In this article we'll see how to adapt to certain requirements, how to generate new templates and use them to render html forms, especially when you can't affect the incoming data. 

Let's say we have a data that looks like:
```json
{
  "name": "Worker",
  "formProperties": [
    {
      "name": "firstName",
      "component": "TextFieldComponent",
      "label": "First Name"
    },
    {
      "name": "lastName",
      "component": "TextFieldComponent",
      "label": "Last Name"
    }
  ]
}
```

Now if we want to render this as an html form, it already looks familiar. One entry in formProperties should correspond to one form row, we have a name, and a label but we are missing a type for our input. Obviously we should use component, but we should do something because there is no TextFieldComponent input type.

Idea is to create a template with one partial which will contain partials for each form property.

```smalltalk
MiniExample >> render: json

templateString := String new writeStream.
templateString nextPutAll: self baseTemplate.
partial := String new writeStream.
parts := Dictionary new.
s := NeoJSONReader fromString: json.
    (s at: 'formProperties') do: [ :el | 
	    | tmp |
	    tmp := self preparePartialTemplate: el.
	    parts at: (el at: 'name') put: tmp.
	    partial nextPutAll: '{{> '.
	    partial nextPutAll: (el at: 'name').
	    partial nextPutAll: '}}'.
    ].

p := partial contents asMustacheTemplate value: '' asDictionary partials: parts.
^ templateString contents asMustacheTemplate value: s partials: {'partial' -> p } asDictionary.
```

Here we can see the `json` argument, it represents the data we want to handle and I am using [NeoJSON](https://github.com/svenvc/NeoJSON) to read JSON and convert it to a Smalltalk object. `templateString` contains the base template for this example, it has a 
 * simple form, 
 * `{{ name }}` template which will directly replaced with `name` from json, 
 * `{{> partial }}` which will be replaced with that many partials, how many entries there are in the `formProperties`, or two in this case.


```smalltalk
MiniExample >> baseTemplate

^
'<form action="http://localhost:8081/addNewEntity" method="post">
    {{ name }}
    {{> partial }}
    <button type="submit" class="btn btn-primary">Submit</button>
</form>'

```

Next we have `partial` which will contain generated partials and it will look like this `{{> firstName}}{{> lastName}}` at the end of iteration, and `parts` dictionary that will hold two templates for the two generated partials. So let's take a deeper look at what `do:` does.

`:el` is a dictionary, it contains a name, component and a label, while `preparePartialTemplate:` is a method that expects a dictionary and returns a template. When the `preparePartialTemplate:` finishes we store the result in the `parts` dictionary, and generate partial that will correspond to that template eg. `{{> firstName}}`.


Here you can organize the template however you want, for the sake of tutorial I'm keeping it simple and in the same place.

```smalltalk
MiniExample >> preparePartialTemplate: dict

templateString := String new writeStream.
templateString nextPutAll:
'
<div class="form-group">
	<label for="{{ label }}">{{ label }}</label>
'.
templateString nextPutAll: (self determineComponent: (dict at: 'component')).
templateString nextPutAll: '</div>'.
^ templateString contents asMustacheTemplate value: { 
	'label' -> (dict at: 'label').
} asDictionary.

```

Also, here when you have your component you can do whatever you want, I'm just keeping it short.

```smalltalk
MiniExample >> determineComponent: aComponent

aComponent = 'TextFieldComponent' ifTrue: [ 
    ^'<input type="text" id="{{label}}" name="{{ label }}" placeholder="Enter {{label}}">']
```

And finally, we have our partial:

```mustache
 partial -> {{> firstName}}{{> lastName}} 
```

and the `parts` dictionary:

```html
firstName ->

<div class="form-group">
	<label for="First Name">First Name</label>
    <input type="text" class="form-control" id="First Name" name="First Name" placeholder="Enter First Name">
</div>

lastName ->

<div class="form-group">
	<label for="Last Name">Last Name</label>
    <input type="text" class="form-control" id="Last Name" name="Last Name" placeholder="Enter Last Name">
</div>

```

Now to return to the first snippet

```smalltalk
p := partial contents asMustacheTemplate value: '' asDictionary partials: parts.
^ templateString contents asMustacheTemplate value: s partials: {'partial' -> p } asDictionary.
```

`p` will get the final form:

```html

<div class="form-group">
	<label for="First Name">First Name</label>
    <input type="text" class="form-control" id="First Name" name="First Name" placeholder="Enter First Name">
</div>
<div class="form-group">
	<label for="Last Name">Last Name</label>
    <input type="text" class="form-control" id="Last Name" name="Last Name" placeholder="Enter Last Name">
</div>
```

And `p` will replace the `{{> partial }}` template in the original `baseTemplate`, and finally get to the

```html
<form action="http://localhost:8081/addNewEntity" method="post">
    {{ name }}
    <div class="form-group">
        <label for="First Name">First Name</label>
        <input type="text" class="form-control" id="First Name" name="First Name" placeholder="Enter First Name">
    </div>
    <div class="form-group">
        <label for="Last Name">Last Name</label>
        <input type="text" class="form-control" id="Last Name" name="Last Name" placeholder="Enter Last Name">
    </div>
    <button type="submit" class="btn btn-primary">Submit</button>
</form>

```

And after evaluating, with a little bit of css tweaking, we get something like this

![Alt Text](https://thepracticaldev.s3.amazonaws.com/i/qpsbfzdzlm2izib2doyh.png)

Now, it is possible to extend your template and add support for other field types, components, requirements, etc.