I'm working with the Twig template engine and want to include a sub-template linke the following example:
<header>
<div id="menu">
{% include 'menu.twig' %}
</div>
</header>
The included file contains the following code:
<ul>
<li>item 1</li>
<li>item 2</li>
</ul>
Now Twig generates the followig HTML code:
<header>
<div id="menu">
<ul>
<li>item 1</li>
<li>item 2</li>
</ul>
</div>
</header>
As you can see the indentation level is only correct for the first line of the included file which leads to the code above which is quite untidy and bad to maintain.
How is it possible to get a correct output from Twig with correct indentation like this?
<header>
<div id="menu">
<ul>
<li>item 1</li>
<li>item 2</li>
</ul>
</div>
</header>
I don't think there is a way to maintain indentation when including templates. The only solution I can imagine would be to pass the indentation level in a variable and use a loop in the included template to prefix that amount of whitespaces in each line. Obviously this "solution" would be crazy and a nightmare to maintain.
Regarding this comment: "[...] which leads to the code above which is quite untidy and bad to maintain." I'd like to say the following:
It doesn't matter if the HTML is "untidy". Browsers won't complain and users won't see it.
It's true that it's bad to maintain. Luckily, you maintain the beautifully aligned Twig template, not the generated HTML code.
All the above would be different if the Twig template was generating a format where "perfect alignment" is mandatory. But in the case of HTML, please don't waste your time aligning the tags.
If you just want to maintain the exact indentation of the included sub-template, you can do this:
<header>
<div id="menu">
{% include 'menu.twig' %}
</div>
</header>
i.e. put all the "include" directives at the beginning of the line. The result will be:
<header>
<div id="menu">
<ul>
<li>item 1</li>
<li>item 2</li>
</ul>
</div>
</header>
But somehow I feel this is not good enough.
Another solution is to add the indentation in the sublayout, i.e.
<ul>
<li>item 1</li>
<li>item 2</li>
</ul>
but of course it only works if the sublayout is always included at a certain level of indentation.
I suggest you take a completely different route and format the response after it is generated, e.g. with a listener on the kernel.response event.
You can add a Twig filter like this after creating your twig environment in php:
$filter = new Twig_Filter('ident', function ($string, $number) {
$spaces = str_repeat(' ', $number);
return rtrim(preg_replace('#^(.+)$#m', sprintf('%1$s$1', $spaces), $string));
}, array('is_safe' => array('all')));
$Your_Twig_Environment->addFilter($filter);
after this you can use it like this :
{{ include('menu.twig')|ident(4) }}
(be careful use include function syntax with {{ }} and not include tag syntax {% %})
Related
I list my categories with wp_list_categories().
When there are subcategories, the result/html gives by default :
<ul>
<li>category parent</li>
<ul class="children">
<li>category children</li>
</ul>
</ul>
I would like to remove the ul list for the catégories children, to have a simple list of categories:
<ul>
<li>category parent</li>
<li>category children</li>
</ul>
Do you know how can it be done?
The easiest way is using jQuery
var innerUl = $(".children").html();
$(".children").remove();
$("ul").append(innerUl);
Or you can use .unwrap(), it would be a better solution.
I have the following array / sub array structure
"filters": {
"types": {
"34": "Ford",
"22": "Jeep",
"18": "Porsche",
},
"locations": [
"Earth",
"Mars",
"Moon",
]
}
and the following handlebars template
{{#if filters}}
{{#each filters}}
<div class="cars">
<ul class="cars__list">
<li class="cars-{{#key}}__title">Filter by {{#key}}:</li>
<li class="cars-{{#key}}__filters">
<ul>
<li class="cars-{{#key}}">View All</li>
{{#each this}}
<li class="cars-{{*want to access filters[key]*}} color={{#key}}">{{this}}</li>
{{/each}}
</li>
</li>
</ul>
</div>
{{/each}}
{{/if}}
I'm having trouble accessing the filters[types] and filters[locations] within the each this loop.
In my CSS I'm using a classes called .cars-type and .cars-location. I want to be able to style each list separately and unfortunately target each li with a class. I want to apply these styles within the each this loop.
I can do it within the filters loop by using {{#key}} but not in the each this loop
I've tried
<li class="cars-{{../filters}}">{{this}}</li>
but this just returns the car type like ford - I want the key ie. '34' in this case
<li class="cars-{{lookup ../filters #index}}">{{this}}</li>
using handlebars helper lookup but again no luck
<li class="cars-{{../this}}">{{this}}</li>
and the above which gives me [object Object]
I've checked out handlebars - is it possible to access parent context in a partial?, handlebars.js: relative paths in partials not working and Lookup helper in handlebars but no luck with any of the solutions
EDIT Here's the HTML output that I want to produce
<div class="cars">
<ul class="cars__list">
<li class="cars-types__title">Filter by types:</li>
<li class="cars-types__filters">
<ul>
<li class="cars-types">View All</li>
<li class="cars-types color-34">Ford</li>
<li class="cars-types color-22">Jeep</li>
<li class="cars-types color-18">Porsche</li>
</ul>
</li>
</ul>
<ul class="cars__list">
<li class="cars-locations__title">Filter by locations:</li>
<li class="cars-locations__filters">
<ul>
<li class="cars-locations">View All</li>
<li class="cars-locations color-0">Earth</li>
<li class="cars-locations color-1">Mars</li>
<li class="cars-locations color-2">Moon</li>
</ul>
</li>
</ul>
</div>
You should reconsider your HTML because a ul cannot be a direct child of another ul. See https://developer.mozilla.org/en/docs/Web/HTML/Element/ul#Usage_context
With that said, we can solve your problem. The Handlebars docs have our answer:
Nested each blocks may access the interation variables via depth based
paths. To access the parent index, for example, {{#../index}} can be
used.
Therefore, your problematic line should look like the following:
<li class="cars-{{#../key}} color-{{#key}}">{{this}}</li>
I have pre compiled all my templates into one js file and loaded the js in the page.
I have 3 templates
Template 1 - a.handlebars
<ul>
{{#each this}}
<li class="a">
{{#key}}
{{> b}}
</li>
{{/each}}
</ul>
Template 2 - b.handlebars
<ul>
{{#each this}}
<li class="b">
{{#key}}
{{> c}}
</li>
{{/each}}
</ul>
Template 3 -c.handlebars
<ul>
{{#each this}}
<li class="c">
{{ this }}
</li>
{{/each}}
</ul>
I have the following JS which load data to the template
var menu= {
a1:{
b1:[c1, c2, c3],
b2: [c4, c5, c6]
},
a2:{
b3:[c7, c8],
b4: [c9]
}
};
Handlebars.templates.a(menu);
The first template (a.handlebars) loads a1 and a2. But when the first template loads the partials b.handlebars it fails. I tried to put a log statement to see what is that I am getting for "this". I got 4 spaces and it was of type string.
I do not understand why b.handlebar is getting a string when I thought I will be getting (example for a1)
{
b1:[c1, c2, c3],
b2: [c4, c5, c6]
}
Previously,I did not pre compile the handlebars. I had all the handlebars in my html and compiled it using Handlebars.compile it worked fine. I do not know why the code is failing after per compiling.
Any help is highly appreciated.
I am trying to get his as my final result:
<ul>
<li class="a">a1
<ul>
<li class="b">b1
<ul>
<li class="c">c1</li>
<li class="c">c2</li>
<li class="c">c3</li>
</ul>
</li>
<li class="b">b2
<ul>
<li class="c">c4</li>
<li class="c">c5</li>
<li class="c">c6</li>
</ul>
</li>
<li class="b">b3</li>
</ul>
</li>
<li class="a">a2
<ul>
<li class="b">b3
<ul>
<li class="c">c7</li>
<li class="c">c8</li>
</ul>
</li>
<li class="b">b4
<ul>
<li class="c">c9</li>
</ul>
</li>
</ul>
</li>
</ul>
But I am getting this. Since the b.handlebars is not getting the object data.
<ul>
<li class="a">a1
<ul>
</ul>
</li>
<li class="a">a2
<ul>
</ul>
</li>
</ul>
My apologies for the very lengthy post. I have been trying to find a solution for this for a while now. Again, any help to resolve this issue would be great.
Thanks.
The issue was caused due to compiling the handlebar/template files using grunt.
Command: "grunt handlebars"
Once I compiled the files using handlers itself, the code started working.
Command: handlebars template_files -f output_file
If anyone knows how to make the compiled code work using grunt command I would definitely would like to know. Thanks.
I am trying to initialize a literal with a big sequence of html code.
for example this is working just fine:
Literal1.Text.= "<ul><li>home<li/><ul/>";//just fine
But:
When i have more than one lines it doesn't work:
Literal1.Text.= "<ul><li>home
</li></ul>";//error
I know a simple solution which is this:
Literal1.Text.= "<ul><li>home"+
"</li></ul>";//nice but time wasting for many lines
But:
When i have 100 lines for example i don't want to spend my time concatenating the strings.Is there any more practical solution?
Specifically my html code is the folowing:
Literal1.Text.= "<ul id="nav">
<li class="current">Home</li>
<li>People
<ul>
<li>Customers
<ul>
<li>View</li>
<li>Edit</li>
<li>Print</li>
<li>Delete</li>
</ul>
</li>
<li>Employees
<ul>
<li>View</li>
<li>Edit</li>
<li>Print</li>
<li>Delete</li>
</ul>
</li>
</ul>
</li>
<li>Quotations
<ul>
<li>Create</li>
<li>Edit</li>
<li>View</li>
</ul>
</li>
<li>Invoices
<ul>
<li>Create</li>
<li>Edit</li>
<li>View</li>
</ul>
</li>
<li>Receipts
<ul>
<li>Create</li>
<li>Edit</li>
<li>View</li>
</ul>
</li>
<li>Statements
<ul>
<li>Create</li>
</ul>
</li>
<li>About Us</li>
<li class="style1">Contact Us</li>
</ul>";
For a small number of lines of code, I generally use StringBuilder. That way there are no performance issues with concatenating large immutable strings.
StringBuilder sb = new StringBuilder();
sb.Add("<ul><li>home");
sb.Add("</li></ul>");
For a large number of lines, don't put them in your code at all. Read them in using System.IO.File, so that you can edit your HTML without worrying about doubling your quotes. If you're using the code a lot, read it in once using a static class so that you're not causing a lot of extra IO usage. Something like this (untested):
public static class HTMLStringClass
{
private static string html;
public static string GetHtmlString()
{
if (string.IsNullOrEmpty(html))
html = File.ReadAllText("path/to/file");
return html;
}
}
And then call it by doing this:
Literal1.Text = HtmlStringClass.GetHtmlString();
Use a verbatim string literal (one that starts with #):
Literal1.Text = #"<ul><li>home
</li></ul>";
Is it possible to have Wordpress generate this type of unordered list?
<ul id="nav1">
<li>item1</li>
<li>item2
<ul id="nav2">
<li>subitem1</li>
</ul></li>
<li>item3</li>
</ul>
Obviously I can do the following:
<ul id="nav1">
<?php wp_list_pages(); ?>
</ul>
But my question is, how do I make it so that I can have a secondary ul under a page (or list item such as 'item2' above)?
Basically, I'm looking for a way for Wordpress to dynamically generate the following:
<li>item2
<ul>
<li>subitem1</li>
</ul></li>
And I can use JQuery if necessary to give the secondary (sub menu) unordered list an id of #nav2...
Anyway, is this possible?
Thanks and I appreciate all of your help!
Amit
Nevermind guys.
I just tried it with the wp_list_page(); function and it works. It does exactly as I wanted it to with exception to one thing...
It put's an extra <ul> in there so the list looks something like this:
<ul id="nav1">
Pages
<ul>
<li>item1
<ul class="children">
<li>sub-item1</li>
</ul></li>
</ul>
</ul>
Anyone know how to get rid of the <ul> following the Pages title, as well as NOT show the word Pages?
Thanks, Amit
Okay, I solved the added ul program.
This is what I have as the result:
<ul id="nav1"><?php
$pageargs = array(
'link_after' => ' /',
'title_li' => __('')
);
wp_list_pages($pageargs); ?></ul>
Hope someone benefits from it :)
Amit