Closed diosney closed 10 years ago
StackOverflow question here: http://stackoverflow.com/questions/19750003/handlebars-how-pass-index-as-parameter-to-custom-helper, just in case if you want to answer there too :D
On this, what I'm trying to accomplish ultimately is to write a helper that gets as parameter an object and a index, and returns object[index](somesort,, is a little more complex than that).
Can you help me to write such a helper with Handlebars.PHP?
Thanks in advance.
handlebars.php doesn't parse arguments of helpers, it's your job to parse and give meaning to them (I'm talking about third parameter that gets passed to helpers, _helper_each($template, $context, $args, $source)
). but in your case, there's no need to parse arguments, you can simply access it by $context->lastIndex()
.
You need to parse the arguments manually inside a helper.
$hdlbars = new Handlebars_Engine();
$hdlbars->getHelpers()->add('content', function($template, $context, $args, $source) {
$args = explode(' ', $args);
foreach( $args as &$arg ) {
if( $arg == '@index' ) {
$arg = $context->lastIndex();
} else {
// Parse variable name.
$arg = $context->get($arg);
}
}
$buffer = "arguments passed: " . implode(', ' $args);
$buffer .= $template->render($context);
return $buffer;
});
@everplays, @boukeversteegh:
1001 Thanks! With your help I was able to do the custom helper!
This was the final implementation, just for the record.
/**
* Handlebars Helper Content. Return object->Alphabet[index].
*
* @param $template
* @param $context
* @param $args
* @param $source
*
* @return Handlebars_String
* @throws InvalidArgumentException
*/
public static function _helper_content($template, $context, $args, $source) {
$Alphabet = range('A', 'Z');
$tmp = explode(' ', $args);
$buffer = '';
$object = $context->get($tmp[0]);
if (count($tmp) < 2 || $tmp[1] == '@index') {
$last_index = $context->lastIndex();
$letter = $Alphabet[$last_index];
}
else {
$index = $context->get($tmp[1]);
$letter = $Alphabet[$index];
}
$buffer .= $object->$letter;
return new Handlebars_String($buffer);
}
Possibly a more holistic solution would be to update the Context::get to handle the the case of @index and @key specifically as I did here
For those interested, here's a way to create powerful templates with custom helpers, while still using but a minimal amount of code :
table.hbs
:{{#if table}}
<table>
<thead>
<tr>
<th style="width: 2%;">#</th>
{{#each table.0}}
<th nowrap="nowrap">
{{uppercase @key}}
</th>
{{/each}}
</tr>
</thead>
<tbody>
{{#each table}}
<tr>
<th>{{increment @index}}</th>
{{#each this}}
<td><input type="text" value="{{this}}" /></td>
{{/each}}
</tr>
{{/each}}
</tbody>
</table>
{{#if paginator}}
<nav class="pagination">
<ul>
{{#each paginator}}
<li><a href="{{this}}">{{@key}}</a></li>
{{/each}}
</ul>
</nav>
{{/if}}
{{else}}
<p>No data found!</p>
{{/if}}
// Create handlebars object
$template_engine = new \Handlebars\Handlebars;
// Get helpers object
$helpers = $template_engine->getHelpers();
// Add 'uppercase' helper
$helpers->add('uppercase', function($template, $context, $args, $source) {
return ucwords($context->get($args));
});
// Add 'increment' helper
$helpers->add('increment', function($template, $context, $args, $source) {
return $context->get($args) + 1;
});
// Render template
echo $template_engine->render(file_get_contents(__DIR__ . '/table.hbs'), array(
'table' => array(
array('name' => 'John', 'profession' => 'programmer', 'city' => 'Leuven'),
array('name' => 'Sam', 'profession' => 'designer', 'city' => 'Aarschot'),
array('name' => 'Tom', 'profession' => 'owner', 'city' => 'Leuven'),
array('name' => 'Steve', 'profession' => 'copywriter', 'city' => 'Brussels'),
array('name' => 'Thomas', 'profession' => 'designer', 'city' => 'Antwerp')
),
'paginator' => array(
'first' => 'http://www.test.com/first',
'1' => 'http://www.test.com/1',
'2' => 'http://www.test.com/2',
'3' => 'http://www.test.com/3',
'last' => 'http://www.test.com/last'
)
));
<table>
<thead>
<tr>
<th style="width: 2%;">#</th>
<th nowrap="nowrap">
Name
</th>
<th nowrap="nowrap">
Profession
</th>
<th nowrap="nowrap">
City
</th>
</tr>
</thead>
<tbody>
<tr>
<th>1</th>
<td><input type="text" value="John" /></td>
<td><input type="text" value="programmer" /></td>
<td><input type="text" value="Leuven" /></td>
</tr>
<tr>
<th>2</th>
<td><input type="text" value="Sam" /></td>
<td><input type="text" value="designer" /></td>
<td><input type="text" value="Aarschot" /></td>
</tr>
<tr>
<th>3</th>
<td><input type="text" value="Tom" /></td>
<td><input type="text" value="owner" /></td>
<td><input type="text" value="Leuven" /></td>
</tr>
<tr>
<th>4</th>
<td><input type="text" value="Steve" /></td>
<td><input type="text" value="copywriter" /></td>
<td><input type="text" value="Brussels" /></td>
</tr>
<tr>
<th>5</th>
<td><input type="text" value="Thomas" /></td>
<td><input type="text" value="designer" /></td>
<td><input type="text" value="Antwerp" /></td>
</tr>
</tbody>
</table>
<nav class="pagination">
<ul>
<li><a href="http://www.test.com/first">first</a></li>
<li><a href="http://www.test.com/1">1</a></li>
<li><a href="http://www.test.com/2">2</a></li>
<li><a href="http://www.test.com/3">3</a></li>
<li><a href="http://www.test.com/last">last</a></li>
</ul>
</nav>
See also :
Setup:
The issue:
Inside the content helper definition I want to access the @index value, say 0,1,2,... but I'm only getting a string!
How can pass as a parameter and access inside the content helper definition the value of @index?