Search code examples
formstemplatesmustachepartials

Use mustache for templating smaller parts for use multiple times in a form


Okay. So I hope this is specific enough. I'm, kind of new to mustache, but see it has great potential, so why not use it.

I'm making a quite big form, and want to have the form built with mustache. So i have started to make the form in mustache and, then i realized i want to template the form-elements. One template for how i want every narrow input, wide input, select etc. to look like. because now i'm repeating myself.

My template and partials are provided through $.ajax get, where the main form template are defined as a mustache file, with html content, and the partials are defined as a mustache file with every template inside -tags.

Variables for mustache to use. This object is somewhat subject for change.

var jsonForm = {
        oneInputField: {
            value:'put your title here',
            rule_set: {
                required: {
                    strName: 'required',
                    strErrorMsg: 'error message'
                }
            }
        },
        oneSelect: {
            options: [
                {value: '- Pick one -', helper: 'helper', select_options: {disable_search: true}},
                {value: 'option1', selected: true},
                {value: 'option2'},
                {value: 'option3'},
                {value: 'option4'}
            ],
            rule_set: {
                required: {
                    strName: 'required',
                    strErrorMsg: 'error message'
                }
            }
        }
    };

How i fetch the data

$.ajax({
            url: 'myForm.mustache',
            type: 'get',
            success: function(template) {
                $.ajax({
                    url: 'myFormElements.mustache',
                    type: 'get',
                    success: function(partials) {
                        var $html = Mustache.render(template, jsonForm.fields, partials);
                        $('div#formContent').html($html);
                        $('div#formContent select').chosen();

                        if (jsonForm.fields.title.length > 1) {
                            $('div#header').html(jsonForm.fields.title);
                        }
                    }
                });
            }
        });

Partials. Would actually like to have it all in separate files, but it doesn't seem to be possible without making a ton of ajax calls, so I keep with my current two mustache templates.

<script type="text/html" id="inputNarrow">
    <label>{{label}}:</label><input value="{{value}}">
        {{#rule_set.required}}<div class="required">*</div>{{/rule_set.required}}
        {{^rule_set.required}}<div class="not-required">&nbsp;</div>{{/rule_set.required}}
    <div class="clearfix"></div>
</script>

and my form-template

<div id="formContainer" class="border-box">

<div class="group-box">
    <p>Fields marked with <span class="required">*</span> are required to complete the form</p>
</div>

<div class="group-box">
    <h2>Partial element test</h2>
    <div class="form-container">
        {{>partials.inputNarrow}} <-- I have to be able to specify what data I want to enter here.
    </div>
    <div class="form-container">
        {{>partials.selectNarrow}} <-- I have to be able to specify what data I want to enter here.
    </div>
</div>

So my question is is it possible for a bigger one big unique mustache-template to use "element"-templates (also in mustache), for rendering?

I am not very open to adding additional libraries to my project, like ICanHaz or similar, since this is for work.

Really sorry if this question is answered before, but I couldn't find it


Solution

  • I found an alternative way of doing what I tried to do. I'm not sure if it's any good, but it does the job.

    I used the possibility of making functions inside the object sent to the main-tempalte "form-template".

    wich looks like this:

    var smallRender = function(url, containerId, objData) {
            $.ajax({
                url: url,
                type: 'get',
                success: function(template) {
                    var $html = Mustache.render(template, objData);
                    var $objContainer = $('div#' + containerId);
                    $objContainer.append($html);
                }
            });
        };
    

    the actual object

    oneInputField: {
            value:'put your title here',
            rule_set: {
                required: {
                    strName: 'required',
                    strErrorMsg: 'error message'
                }
            },
            getRendered: function() { // I would like to cache this somehow
                smallRender(templateUrl.input.narrow, jsonForm.fields.title.containerId, {
                                label: jsonForm.labels.title,
                                field: jsonForm.fields.title,
                                required: isRequired(jsonForm.fields.title)
                 });
            }
        },
    

    So basicly i send an ajax call to get the main template, and for each element in the form I want to present, i call on the getRendered in main-tamplate mustache, and it basicly renders the content with the smaller template. tempalte url is basicly a collections with the urls to all the templates. so if I specify templateUrl.input.narrow i will get the narrow input element and so on.

    Not sure as I mentioned if this is the "correct" way of doing it, or how good it will scale in a big environment, but it works.

    I will mark my this as the correct answer (if I'm even allowed), since there are no other answers that solves my problem.