0

I found this fiddle that shows how to include multiple partials in a Mustache template: http://jsfiddle.net/YW5zF/3/

I'm trying to convert this to PHP Mustache and having some difficulty. Can anyone help out here?

Essentially, I'm trying to understand how to reuse the input template several times in one template.

Here's my main template (contact.mustache):

<form id="contact-form" method="post" action="contact.php" role="form">
    <div class="messages"></div>
    <div class="controls">
        <div class="row">
            <div class="col-md-6">
                {{>input}}
            </div>
            <div class="col-md-6">
                {{>input}}
            </div>
        </div>
        <div class="row">
            <div class="col-md-6">
                {{>input}}
            </div>
            <div class="col-md-6">
                {{>input}}
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
                {{>textarea}}
            </div>
            <div class="col-md-12">
                <input type="submit" class="btn btn-success btn-send" value="Send message">
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
                <p class="text-muted"><strong>*</strong> These fields are required.</p>
            </div>
        </div>
    </div>
</form>

Here's my input partial (input.mustache):

{{#input}}
    <div class="{{div_class}}">
        <label class="{{label_class}}" for="{{id}}">{{text}}</label>
        <input type="{{type}}" id="{{id}}" name="{{name}}" class="{{input_class}}" placeholder="{{placeholder}}" {{required}} data-error="{{data-error}}">
        <div class="{{line_class}}"></div>
    </div>
{{/input}}

Here's my textarea template (textarea.mustache)

{{#textarea}}
    <div class="{{div_class}}">
        <label class="{{label_class}}" for="{{id}}">{{text}}</label>
        <textarea id="{{id}}" name="{{name}}" class="{{input_class}}" placeholder="{{placeholder}}" rows="{{rows}}" {{required}} data-error="{{data-error}}"></textarea>
        <div class="{{line_class}}"></div>
    </div>
{{/textarea}}

Here's my PHP code to try to render it:

<?php

require_once __DIR__ . '/vendor/autoload.php';

$m = new Mustache_Engine;
    $data = array(
                    0 =>array(
                        "div_class"=>"form-group", 
                        "id"=>"form_name",
                        "type"=>"text",
                        "name"=>"name",
                        "placeholder"=> "Please enter your firstname *",
                        "required"=>"required='required'"
                        "data-error"=>"Firstname is required.",
                        "input_class"=>"form-control", 
                        "label_class"=>"floating-label",
                        "text"=>"Firstname *",
                        "line_class"=>"line-ripple",
                    ),
                    1=> array(
                        "div_class"=>"form-group", 
                        "id"=>"form_lastname",
                        "type"=>"text",
                        "name"=>"surname",
                        "placeholder"=> "Please enter your lastname *",
                        "required"=>"required='required'"
                        "data-error"=>"Lastname is required.",
                        "input_class"=>"form-control", 
                        "label_class"=>"floating-label",
                        "text"=>"Lastname *",
                        "line_class"=>"line-ripple",
                    ),
                    2 =>array(
                        "div_class"=>"form-group", 
                        "id"=>"form_email",
                        "type"=>"email",
                        "name"=>"email",
                        "placeholder"=> "Please enter your email *",
                        "required"=>"required='required'"
                        "data-error"=>"Valid email is required.",
                        "input_class"=>"form-control", 
                        "label_class"=>"floating-label",
                        "text"=>"Email *",
                        "line_class"=>"line-ripple",
                    ),
                    3 =>array(
                        "div_class"=>"form-group", 
                        "id"=>"form_phone",
                        "type"=>"tel",
                        "name"=>"phone",
                        "placeholder"=> "Please enter your phone",
                        "input_class"=>"form-control", 
                        "label_class"=>"floating-label",
                        "text"=>"Phone",
                        "line_class"=>"line-ripple",
                    ),
                    4 =>array(
                        "div_class"=>"form-group", 
                        "id"=>"form_message",
                        "name"=>"message",
                        "placeholder"=> "Message for me *",
                        "required"=>"required='required'"
                        "data-error"=>"Please,leave us a message.",
                        "input_class"=>"form-control", 
                        "label_class"=>"floating-label",
                        "rows"=>4,
                        "text"=>"Message *",
                        "line_class"=>"line-ripple",
                    )
      );

// main templates in the /views folder, partials in the /views/partials folder
$m = new Mustache_Engine(array(
    'loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__) . '/views'),
    'partials_loader' => new Mustache_Loader_FilesystemLoader(dirname(__FILE__) . '/views/partials'),
));

// loads template from `views/contact.mustache` and renders it.
echo $m->render("contact", $data);

Current results of this script is:

<form id="contact-form" method="post" action="contact.php" role="form">
    <div class="messages"></div>
    <div class="controls">
        <div class="row">
            <div class="col-md-6">
                    <div class="form-group">
                        <label class="floating-label" for="form_name">Firstname *</label>
                        <input type="text" id="form_name" name="name" class="form-control" placeholder="Please enter your firstname *" required='required' data-error="Firstname is required.">
                        <div class="line-ripple"></div>
                    </div>
                    <div class="form-group">
                        <label class="floating-label" for="form_lastname">Lastname *</label>
                        <input type="text" id="form_lastname" name="surname" class="form-control" placeholder="Please enter your lastname *" required='required' data-error="Lastname is required.">
                        <div class="line-ripple"></div>
                    </div>
                    <div class="form-group">
                        <label class="floating-label" for="form_email">Email *</label>
                        <input type="email" id="form_email" name="email" class="form-control" placeholder="Please enter your email *" required='required' data-error="Valid email is required.">
                        <div class="line-ripple"></div>
                    </div>
                    <div class="form-group">
                        <label class="floating-label" for="form_phone">Phone</label>
                        <input type="tel" id="form_phone" name="phone" class="form-control" placeholder="Please enter your phone"  data-error="">
                        <div class="line-ripple"></div>
                    </div>
                    <div class="form-group">
                        <label class="floating-label" for="form_message">Message *</label>
                        <input type="" id="form_message" name="message" class="form-control" placeholder="Message for me *" required='required' data-error="Please,leave us a message.">
                        <div class="line-ripple"></div>
                    </div>
            </div>
            <div class="col-md-6">
                    <div class="form-group">
                        <label class="floating-label" for="form_name">Firstname *</label>
                        <input type="text" id="form_name" name="name" class="form-control" placeholder="Please enter your firstname *" required='required' data-error="Firstname is required.">
                        <div class="line-ripple"></div>
                    </div>
                    <div class="form-group">
                        <label class="floating-label" for="form_lastname">Lastname *</label>
                        <input type="text" id="form_lastname" name="surname" class="form-control" placeholder="Please enter your lastname *" required='required' data-error="Lastname is required.">
                        <div class="line-ripple"></div>
                    </div>
                    <div class="form-group">
                        <label class="floating-label" for="form_email">Email *</label>
                        <input type="email" id="form_email" name="email" class="form-control" placeholder="Please enter your email *" required='required' data-error="Valid email is required.">
                        <div class="line-ripple"></div>
                    </div>
                    <div class="form-group">
                        <label class="floating-label" for="form_phone">Phone</label>
                        <input type="tel" id="form_phone" name="phone" class="form-control" placeholder="Please enter your phone"  data-error="">
                        <div class="line-ripple"></div>
                    </div>
                    <div class="form-group">
                        <label class="floating-label" for="form_message">Message *</label>
                        <input type="" id="form_message" name="message" class="form-control" placeholder="Message for me *" required='required' data-error="Please,leave us a message.">
                        <div class="line-ripple"></div>
                    </div>
            </div>
        </div>
        <div class="row">
            <div class="col-md-6">
                    <div class="form-group">
                        <label class="floating-label" for="form_name">Firstname *</label>
                        <input type="text" id="form_name" name="name" class="form-control" placeholder="Please enter your firstname *" required='required' data-error="Firstname is required.">
                        <div class="line-ripple"></div>
                    </div>
                    <div class="form-group">
                        <label class="floating-label" for="form_lastname">Lastname *</label>
                        <input type="text" id="form_lastname" name="surname" class="form-control" placeholder="Please enter your lastname *" required='required' data-error="Lastname is required.">
                        <div class="line-ripple"></div>
                    </div>
                    <div class="form-group">
                        <label class="floating-label" for="form_email">Email *</label>
                        <input type="email" id="form_email" name="email" class="form-control" placeholder="Please enter your email *" required='required' data-error="Valid email is required.">
                        <div class="line-ripple"></div>
                    </div>
                    <div class="form-group">
                        <label class="floating-label" for="form_phone">Phone</label>
                        <input type="tel" id="form_phone" name="phone" class="form-control" placeholder="Please enter your phone"  data-error="">
                        <div class="line-ripple"></div>
                    </div>
                    <div class="form-group">
                        <label class="floating-label" for="form_message">Message *</label>
                        <input type="" id="form_message" name="message" class="form-control" placeholder="Message for me *" required='required' data-error="Please,leave us a message.">
                        <div class="line-ripple"></div>
                    </div>
            </div>
            <div class="col-md-6">
                    <div class="form-group">
                        <label class="floating-label" for="form_name">Firstname *</label>
                        <input type="text" id="form_name" name="name" class="form-control" placeholder="Please enter your firstname *" required='required' data-error="Firstname is required.">
                        <div class="line-ripple"></div>
                    </div>
                    <div class="form-group">
                        <label class="floating-label" for="form_lastname">Lastname *</label>
                        <input type="text" id="form_lastname" name="surname" class="form-control" placeholder="Please enter your lastname *" required='required' data-error="Lastname is required.">
                        <div class="line-ripple"></div>
                    </div>
                    <div class="form-group">
                        <label class="floating-label" for="form_email">Email *</label>
                        <input type="email" id="form_email" name="email" class="form-control" placeholder="Please enter your email *" required='required' data-error="Valid email is required.">
                        <div class="line-ripple"></div>
                    </div>
                    <div class="form-group">
                        <label class="floating-label" for="form_phone">Phone</label>
                        <input type="tel" id="form_phone" name="phone" class="form-control" placeholder="Please enter your phone"  data-error="">
                        <div class="line-ripple"></div>
                    </div>
                    <div class="form-group">
                        <label class="floating-label" for="form_message">Message *</label>
                        <input type="" id="form_message" name="message" class="form-control" placeholder="Message for me *" required='required' data-error="Please,leave us a message.">
                        <div class="line-ripple"></div>
                    </div>
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
            </div>
            <div class="col-md-12">
                <input type="submit" class="btn btn-success btn-send" value="Send message">
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
                <p class="text-muted"><strong>*</strong> These fields are required.</p>
            </div>
        </div>
    </div>
</form>

Why isn't it doing it correctly?

EDIT Finally got it working, changes are listed below...

Here's contact.mustache

<form id="contact-form" method="post" action="contact.php" role="form">
    <div class="messages"></div>
    <div class="controls">
        {{>input}}
        {{>textarea}}
        <div class="col-md-12">
            <input type="submit" class="btn btn-success btn-send" value="Send message">
        </div>
        <div class="row">
            <div class="col-md-12">
                <p class="text-muted"><strong>*</strong> These fields are required.</p>
            </div>
        </div>
    </div>
</form>

Here's input.mustache

{{#input}}
<div class="row">
    <div class="col-md-6">
        <div class="{{div_class}}">
            <label class="{{label_class}}" for="{{id}}">{{text}}</label>
            <input type="{{type}}" id="{{id}}"    name="{{name}}" class="{{input_class}}" placeholder="{{placeholder}}" {{required}} data-error="{{data-error}}">
            <div class="{{line_class}}"></div>
        </div>
    </div>
</div>
{{/input}}

Here's textarea.mustache

{{#textarea}}
<div class="row">
    <div class="col-md-12">
        <div class="{{div_class}}">
            <label class="{{label_class}}" for="{{id}}">{{text}}</label>
            <textarea id="{{id}}" name="{{name}}" class="{{input_class}}" placeholder="{{placeholder}}" rows="{{rows}}" {{required}} data-error="{{data-error}}"></textarea>
            <div class="{{line_class}}"></div>
        </div>
    </div>
</div>
{{/textarea}}

Here's the data array (code stays same):

$data = array(
    "input"=>array(
                0 =>array(
                    "div_class"=>"form-group", 
                    "id"=>"form_name",
                    "type"=>"text",
                    "name"=>"name",
                    "placeholder"=> "Please enter your firstname *",
                    "required"=>"required='required'",
                    "data-error"=>"Firstname is required.",
                    "input_class"=>"form-control", 
                    "label_class"=>"floating-label",
                    "text"=>"Firstname *",
                    "line_class"=>"line-ripple",
                ),
                1=> array(
                    "div_class"=>"form-group", 
                    "id"=>"form_lastname",
                    "type"=>"text",
                    "name"=>"surname",
                    "placeholder"=> "Please enter your lastname *",
                    "required"=>"required='required'",
                    "data-error"=>"Lastname is required.",
                    "input_class"=>"form-control", 
                    "label_class"=>"floating-label",
                    "text"=>"Lastname *",
                    "line_class"=>"line-ripple",
                ),
                2 =>array(
                    "div_class"=>"form-group", 
                    "id"=>"form_email",
                    "type"=>"email",
                    "name"=>"email",
                    "placeholder"=> "Please enter your email *",
                    "required"=>"required='required'",
                    "data-error"=>"Valid email is required.",
                    "input_class"=>"form-control", 
                    "label_class"=>"floating-label",
                    "text"=>"Email *",
                    "line_class"=>"line-ripple",
                ),
                3 =>array(
                    "div_class"=>"form-group", 
                    "id"=>"form_phone",
                    "type"=>"tel",
                    "name"=>"phone",
                    "placeholder"=> "Please enter your phone",
                    "input_class"=>"form-control", 
                    "label_class"=>"floating-label",
                    "text"=>"Phone",
                    "line_class"=>"line-ripple",
                ),
            ),
"textarea"=>array(
                0 =>array(
                    "div_class"=>"form-group", 
                    "id"=>"form_message",
                    "name"=>"message",
                    "placeholder"=> "Message for me *",
                    "required"=>"required='required'",
                    "data-error"=>"Please,leave us a message.",
                    "input_class"=>"form-control", 
                    "label_class"=>"floating-label",
                    "text"=>"Message *",
                    "rows"=>4,
                    "line_class"=>"line-ripple",
                ),
            )
  );

Here's Output:

<form id="contact-form" method="post" action="contact.php" role="form">
    <div class="messages"></div>
    <div class="controls">
        <div class="row">
            <div class="col-md-6">
                <div class="form-group">
                    <label class="floating-label" for="form_name">Firstname *</label>
                    <input type="text" id="form_name"    name="name" class="form-control" placeholder="Please enter your firstname *" required='required' data-error="Firstname is required.">
                    <div class="line-ripple"></div>
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col-md-6">
                <div class="form-group">
                    <label class="floating-label" for="form_lastname">Lastname *</label>
                    <input type="text" id="form_lastname"    name="surname" class="form-control" placeholder="Please enter your lastname *" required='required' data-error="Lastname is required.">
                    <div class="line-ripple"></div>
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col-md-6">
                <div class="form-group">
                    <label class="floating-label" for="form_email">Email *</label>
                    <input type="email" id="form_email"    name="email" class="form-control" placeholder="Please enter your email *" required='required' data-error="Valid email is required.">
                    <div class="line-ripple"></div>
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col-md-6">
                <div class="form-group">
                    <label class="floating-label" for="form_phone">Phone</label>
                    <input type="tel" id="form_phone"    name="phone" class="form-control" placeholder="Please enter your phone"  data-error="">
                    <div class="line-ripple"></div>
                </div>
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
                <div class="form-group">
                    <label class="floating-label" for="form_message">Message *</label>
                    <textarea id="form_message" name="message" class="form-control" placeholder="Message for me *" rows="4" required='required' data-error="Please,leave us a message."></textarea>
                    <div class="line-ripple"></div>
                </div>
            </div>
        </div>
        <div class="col-md-12">
            <input type="submit" class="btn btn-success btn-send" value="Send message">
        </div>
        <div class="row">
            <div class="col-md-12">
                <p class="text-muted"><strong>*</strong> These fields are required.</p>
            </div>
        </div>
    </div>
</form>
MB34
  • 4,210
  • 12
  • 59
  • 110

1 Answers1

1

What actually helped
The PHP render function seems to only have two parameters, unlike the Javascript one. So removing the third parameter and renaming {{>objPartial}} to {{>input}} so it matches the file should make it work with the PHP renderer.

Also, each time a partial is encountered in the main template, it will look at the data it's been given and create the code from the partial for each index of the array. The way your code is would work perfectly if each appearance of the partial only rendered for one element of the array.

At this point, you've very nearly got it working, just need to tweak a couple more things.

{{#input}}
 <div class="col-md-6">
  <div class="{{div_class}}">
   <label class="{{label_class}}" for="{{id}}">{{text}}</label>
   <input type="{{type}}" id="{{id}}" name="{{name}}" class="{{input_class}}" placeholder="{{placeholder}}" {{required}} data-error="{{data-error}}">
   <div class="{{line_class}}"></div>
  </div>
{{/input}}

And in the main template just have one reference to {{>input}}.

<form id="contact-form" method="post" action="contact.php" role="form">
    <div class="messages"></div>
    <div class="controls">
        <div class="row">
           {{>input}}
        </div>
        <div class="row">
            <div class="col-md-12">
                {{>textarea}}
            </div>
            <div class="col-md-12">
                <input type="submit" class="btn btn-success btn-send" value="Send message">
            </div>
        </div>
        <div class="row">
            <div class="col-md-12">
                <p class="text-muted"><strong>*</strong> These fields are required.</p>
            </div>
        </div>
    </div>
</form>

There is a way to retain the format of one row div per two elements, but with bootstrap columns it's not necessary unless you're doing some sort of special formatting.

Old answer (retained in case it is useful for someone else)
There's a slight tweak here that I believe will make this work. Rather than calling the partial for each piece of content, call it once for the whole array of content. Your $data array would need to be slightly different, so here's what I'm seeing:

$data = array(
  "input"=>array(
    array(
      "div_class"=>"text-field", "id"=>"firstName",
      "input_class"=>"text-field__input", "label_class"=>"floating-label",
      "line_class"=>"line-ripple", "text"=>"Curly"
     )
    ),
    array(
       "div_class"=>"text-field", "id"=>"lastName",
       "input_class"=>"text-field__input",
       "label_class"=>"floating-label",
       "line_class"=>"line-ripple", "text"=>"Athos"
    )
  )
);

And your partial would change slightly to include the .col-md-6:

{{#input}}
<div class="col-md-6">
  <div class="{{div_class}}">
    <input type="text" id="{{id}}" class="{{input_class}}">
    <label class="{{label_class}}" for="{{id}}">{{text}}</label>
    <div class="{{line_class}}"></div>
  </div>
</div>
{{/input}}

Then you can replace

<div class="row">
    <div class="col-md-6">
        {{#firstname}}
            {{>objPartial}}
        {{/firstname}}
    </div>
    <div class="col-md-6">
        {{#lastname}}
            {{>objPartial}}
        {{/lastname}}
    </div>
</div>

with

<div class="row">
  {{>objPartial}}
</div>
D. Kendall
  • 316
  • 2
  • 9
  • That returns only `
    `. Am I rendering it correctly?
    – MB34 May 24 '18 at 15:19
  • Ah, it looks like I lost a parenthesis while I was editing the array, I'll go ahead and correct that. – D. Kendall May 24 '18 at 19:55
  • Also, did you tweak the array to use 0-indexed input array? – D. Kendall May 24 '18 at 19:57
  • 1. the array change didn't work, 2. I'm not using indexes. – MB34 May 24 '18 at 20:16
  • Hmm, your original array had string indexes 'firstname' and 'lastname', changing those to either 0 and 1 or just automatically assigned allows mustache to iterate through the elements in the array and create html content for each. If that's still not working, there must be something I'm missing. I'm looking into it a bit and I'll let you know if I find anything potentially useful. – D. Kendall May 25 '18 at 01:59
  • So after a bit of looking around, I can't find any reference to a third parameter in the render function for PHP, so perhaps what's needed is just to remove the array('objPartial' => 'input') and change the {{> objPartial }} to {{> input }} – D. Kendall May 25 '18 at 02:14
  • The jsfiddle example used `to_html()` and it had the 3 params. – MB34 May 25 '18 at 13:44
  • Take a look at my edit above. Post your suggestion as answer for points. – MB34 May 25 '18 at 14:04
  • Glad it helped, and will do. – D. Kendall May 25 '18 at 14:29
  • Look at the updated post. I used your technique to build a contact form with multiple edits and it didn't quite come out as I expected. – MB34 May 25 '18 at 14:36