Call function in twig.js file - node.js

I'm creating an express application and for the views render I use twig.js.
I'm displaying some posts from mongodb into index.twig file. The question is how can I call a function from a js file(let's call it Utils.js) in the twig file?
My index.twig file looks something like this:
<div class="post-date">{{ post["date"] }}</div>
<div class="post-body">
{{ post["body"] }}
</div>
What I need to do is to format that post["date"] calling a method from Utils.js not just echoing it out as it is. How can I do that ?
P.S. I know that there are filters for date but I want my own data format.

The question was answered here: https://github.com/justjohn/twig.js/issues/206#issuecomment-73443040
To add a filter you can use Twig.extendFilter():
Twig.extendFilter('foo', function (value) {
return util.format(value);
});
After adding a filter you'll be able to use it in your templates:
{{ value|foo }}

Related

OpenCart 3.x - including a new template file

I need to add a new OpenCart template file into another template file.
Essentially I've created a new head file in /theme/customtheme/template/common/ called "header_home.twig".
Then in home.twig, I've changed {{ header }} to say {{ header_home }}, but it's not displaying anything.
Basically, all I did was copy header.twig and rename it to header_home.twig, and put in "xxxxx" to see if it was calling the new file, which it's not. Instead, it's not displaying anything.
Here's what my home.twig now looks like:
{{ header_home }}
<div id="common-home" class="container">
<div class="row">{{ column_left }}
{% if column_left and column_right %}
{% set class = 'col-sm-6' %}
{% elseif column_left or column_right %}
{% set class = 'col-sm-9' %}
{% else %}
{% set class = 'col-sm-12' %}
{% endif %}
<div id="content" class="{{ class }}">{{ content_top }}{{ content_bottom }}</div>
{{ column_right }}</div>
</div>
{{ footer }}
I assume I'm somehow missing a step when it comes to adding a new template file? If someone could help me with adding in a new twig file, that would be fantastic.
You can either:
Change the name of Twig rendering template on the OpenCart level in the controller/common/header as #bogalakon pointed out (preferably to do this via ocmod so that your future OpenCart updates will not overwrite your hack).
or include another template on the Twig level
I.e.:
{{ header }} {# Original rendered to HTML OpenCart header - you can move it to your header_home.twig or just drop it #}
{% include customtheme/template/common/header_home.twig %}
<div id="common-home" class="container">
...
Twig is very powerful template language. And you can do much more than just a simple include! It's nice that OpenCart officially accepted it. But for now it's just Twig 1.24.2. Please refer to the Twig documentation.
I haven't learn OpenCart 3.x, but I guess you need to change
return $this->load->view('common/header', $data);
to
return $this->load->view('common/header_home', $data);
in catalog/controller/common/header.php.
In order to connect another template via the {{header_home}} construct, you need to create the header_home.php in the folder /controller/common/directory, create the header_home.twig file in the theme /*theme_name*/template/common/ folder and in the controller , which is responsible for the formation of the page, for example in the directory /controller/common/home.php
add a line:
'$ data [' header_home '] = $ this-> load-> controller (' common / header_home '); '
before:
'$ this-> response-> setOutput ($ this-> load-> view (' common / home ', $ data)); '
To add your own custom twig file and include it inside another existing one you need to do three things:
Create the actual custom twig file.
In your case it will be:
catalog/view/theme/customtheme/template/common/header_home.twig
Create a controller for that twig file. In your case you can just copy:
/catalog/controller/common/header.php and rename that to header_home.php. Edit this controller and change the class name to ControllerCommonHeaderHome usually on line 2.
Lastly, since you are going to include header_home inside home.twig, edit /catalog/controller/common/home.php and add the line $data['header'] = $this->load->controller('common/header_home'); after $data['header'] = $this->load->controller('common/header');
That's it. After you've done the steps above, you can now include {{ header_home }} inside home.twig. If you are editing the files directly, I find that sometimes I need to login to the admin of the website, go to design>theme editor, open up the files I added or changed, hit reset, and save. Refresh your website and you should see the changes.
The answer of #bogalakon is right but if you update your OpenCart core files you will lose your changes so, I suggest you to copy the header.php controller file and rename it to header_home.php and then edit the file and replace the line
return $this->load->view('common/header', $data);
with:
return $this->load->view('common/header_home', $data);
There are several ways to give a different value.
For example:
Consider the controller
$data['header'] = $this-> load-> controller ('common / header');
A variable {{header}} is available in the template
You can place a new template in another file (header_home.twig), and then you can immediately download a new template for use:
$data['**header**'] = $this-> load-> controller ('common / ***header_home***');
If you want use {{header}} in the template.
Or,
$data['**header_home**'] = $this-> load-> controller ('common / header_home');
For use {{header_home}} in the template.

Call Helper functions inside Twig (Timber)

I try to call a static helper method inside Twig (Timber).
{{ function('Theme\Helpers::get_template_name') }}
Warning: call_user_func_array() expects parameter 1 to be a valid
callback, class 'ThemeHelpers' not found in
/var/www/html/wp-content/plugins/timber-library/lib/Twig.php on line
268.
Does anyone know how to call a method of a different class inside Twig?
As far as I know you can't call PHP classes directly from your twig template.
What you can do is setting up a Twig filter which communicates with your class
and returns the needed value.
You would have this in your php controller file that is responsible to load your twig template:
<?php
function twg_get_template_name() {
# edit this according to the implementation of your class:
return Helpers::get_template_name();
}
function add_to_twig($twig) {
/* this is where you can add your own fuctions to twig */
$twig->addExtension(new Twig_Extension_StringLoader());
$twig->addFilter('twg_get_template_name', new Twig_Filter_Function('twg_get_template_name'));
return $twig;
}
add_filter('get_twig', 'add_to_twig');
In your Twig template you would call the filter like this:
{{ ''|twg_get_template_name }}
Because it's a filter function it expects a value "to filter", so pass at least an empty string.
If I were in that situation I probably would determine the name of the template in your
controller and send the value to your Twig template directly instead of calling the php class
via a filter-function.
You can call static functions from a Twig file in Timber using the array notation, where first item is the name of the class and the second item the name of the static method you want to call:
{{ function( [ 'Theme\Helpers', 'get_template_name' ] ) }}
Thanks for your answer.
I tried your approach - it works. But using a filter feels a little hacky, especially when no value is passed. Why not create a timber function the same way as a filter?
Bridging own functions from plain php into twig is not great, but I also don't see another solution to this.
After playing around a little, I came up with a different approach. I now fixed my need by customizing the Timber Object and adding a template property to the post variable.
Looks something like this:
class OnepagePost extends TimberPost {
var $_template;
// Add template property to Twig Object
public function template() {
return Helpers::get_template_name( $this->custom['_wp_page_template'] );
}
}
Then inside the .php file where the Twig View gets called, I called the custom object like this:
$context['posts'] = new Timber\PostQuery( $args, 'OnepagePost' );
Timber::render('onepager.twig', $context);
Inside the Twig Template I'm able to get my custom property very easy (in my way the template):
{% for post in posts %}
{% include ["section/section-#{post.template}.twig"] %}
{% endfor %}

How to get route link in Slim3 Twig?

I defined my route so:
$app->get('/about', function ($request, $response, $args) {
return $this->view->render($response, 'about.twig');
})->setName('about.page');
I'm interested to get route link by name like: {% get_route('about.page') %}
How can I achieve this?
In Slim3 there is the path_for(name) function. F.ex:
{{ path_for('about.page') }}
Reference: http://www.slimframework.com/docs/features/templates.html
The slim/twig-view component exposes a custom path_for() function to your Twig templates. You can use this function to generate complete URLs to any named route in your Slim application. The path_for() function accepts two arguments:
1 A route name
2 A hash of route placeholder names and replacement values
Note: The path_for uses the function of the router which is $router->pathFor(..)
Why not to use {%
{% is a control structur in twig, Message: Unknown "path_for" tag in "base.twig" at line XX. is displayed because there is no such tag as control structur defined so twig doesn't know that this is actually a function.
So use the output structur in twig {{.
Is this possible?
Yes.
IIRC
{{ path_for('about.page') }}
Reference:
https://github.com/slimphp/Twig-View/blob/master/src/TwigExtension.php#L37

What is the correct way to pass static HTML files to template?

For example, let's say I have a HandleBars template called main.handlebars like this:
<html>
<head></head>
<body>
<div> {{ html1 }} </div>
<div> {{ html2 }} </div>
<div> {{ html3 }} </div>
</body>
And then I have html1.html:
<p1>Blah</p1>
html2.html:
<p1>Blah</p1>
html3.html:
<p1>Blah</p1>
What's the correct way to load html1.html, html2.html, and html3.html and pass them to the main.handlebars template?
You may need to provide more information on what you are trying to achieve.
However, generally when using a client-side templating library like Handlebars or Mustache you will first compile your template, then pass your data object to the compiled template function.
Using your example above:
<body>
<div> {{ html1 }} </div>
<div> {{ html2 }} </div>
<div> {{ html3 }} </div>
</body>
You would first compile the template:
var template = Handlebars.compile(document.querySelector('body').innerHTML);
Then output the result using a data object, or model:
var output = document.querySelector('.output');
output.innerHTML = template(data);
I've created a simple working example here: http://codepen.io/chrsr/pen/ZQvgEx
If, what you're trying to do, is take the "html" files with the content: <p1>blah</p1> you will need to transform these files in to a readable format by the template library.
Note: <p1> is not a valid HTML element, where are these coming from?
To do this, you could use something like this: http://codepen.io/chrsr/pen/PZEMZz?editors=1010 - a simple example of manipulating your <p1>blah</p1> data in to a JS object).
I've explained the basic concepts of a templating library like Handlebars, but if you're after a different answer I would suggest setting up a CodePen demo or providing more information in your question.

Twig : Access to variable from outer scope in a form widget customization

I'm trying to customize a specific widget, like in the documentation : http://symfony.com/doc/current/cookbook/form/form_customization.html#how-to-customize-an-individual-field
The problem is that in this custom block, I need to use a variable from my actual template. I thought "blocks have access to variables from outer scopes", but apparently not in this case :
{% extends "CDASvBundle::layout.html.twig" %}
{% block _contact_activity1_widget %}
<select name="contact[activity1]">
{% for key, child_contact_categories in contact_categories_tab %}
<option value="{{key}}">{{child_contact_categories}}</option>
{% endfor %}
</select>
It's saying that contact_categories_tab is undefined, but outside of this block (in the normal content block for example), it works !
I tried something like :
{% use 'form_div_layout.html.twig' with contact_categories_tab as contact_categories_tab %}
But that doesn't either.. Though I'm not sure I understand if I have to use use and how !
I see one other solution that I haven't tried yet : put this customization in another template. But I don't really want to do that (few lines in a new template), there should be a way to do that in only ONE template ?!
Finally found the answer in a previous post :
Each symfony form type extents AbstractType class.
AbstactType class has method:
public function buildView(FormView $view, FormInterface $form, array $options)
{
$view->set('img_src', '120x100.jpg');
$view->set('my_variable', $foo);
}
You can create this method on your form type and next in your twig:
{{ asset(img_src) }}
Source : How to get entity or pass variable to Symfony2 twig form widget?

Resources