Twig: Append to array inside array/object - arrays

I have an object which, in JSON, would look like this:
{
'class': ['nav-link', 'dropdown-toggle'],
'data-toggle': ['dropdown']
}
I need to then be able to append another class to the class array inside the object.
This code doesn't seem to work; it just overwrites the class array.
{% set link_attribs = { 'class' : ['nav-link', 'dropdown-toggle'], 'data-toggle':'dropdown'} %}
{% set link_attribs = link_attribs|merge({'class': ['highlighted']}) %}
Really I want to do something like this, but it just throws a punctuation error.
{% set link_attribs.class = link_attribs.class|merge(['highlighted']) %}
Any ideas?

Using Twig, you can't set object properties directly, so "set (...).class" will never work. But instead, you can create a new variable that will inherit from both default and options values (just like in most JavaScript codes).
For example:
{%
set options = link_attribs | merge({
'class': link_attribs.class | merge(['highlighted'])
})
%}
{% for class in options.class %}
{{ class }}
{% endfor %}
Will display:
nav-link
dropdown-toggle
highlighted
See fiddle.

This looks like it works:
{% set c = link_attribs.class %}
{% set c = c|merge(['highlighted']) %}
{% set link_attribs = link_attribs|merge({'class': c}) %}
Not sure if its the most elegant way though.

Related

In Twig: Check if array element exists. If not set this one element

In Twig, I pass an array params to a macro. Within the macro I check if all required elements (here: required_element) of params are set. If not, I want to set that to a default value.
This code is working, but I think there must be a better way:
{% macro my_macro(params) %}
{% if not params.required_element is defined %}
{% set params = params|merge({'required_element: 'value'}) %}
{% endif %}
I thought of something shorter like {% params.required_element ?: value %}, but that does not work.
For various reasons I do not want pass them one by one as parameters to the macro, so this is not an alternative:
{% macro my_macro(required_element, another_element, yet_another, puh_another, next_element) %}
Nope, that is the only (vanilla) way. If you want to make it shorter u'd need to extend twig with something like this:
<?php
$twig = new \Twig\Environment($loader);
$function = new \Twig\TwigFunction('set_array_value', function (&$context, $array_name, $index, $value) {
if (!isset($context[$array_name])) return;
/**
- If value is array just do arr[index] = value
- Otherwise test if object
-> test if method $index exists
-> test if there is a setter for the property $index
**/
if (is_array($context[$array_name])) $context[$array_name][$index] = $value;
elseif(is_object($context[$array_name])) {
if (method_exists($context[$array_name], $index)) $context[$array_name]->{$index}($value);
elseif(method_exists($context[$array_name], 'set'.$index)) $context[$array_name]->{'set'.$index}($value);
}
}, ['needs_context' => true, ]);
$twig->addFunction($function);
{% macro foo(my_array) %}
{% if not array.foo is defined %}{% do set_array_value('my_array', 'foo', 'bar') %}{% endif %}
{{ my_array.foo }}
{% endmacro %}
{% import _self as sandbox %}
{{ sandbox.foo({}) }} #output: bar
{{ sandbox.foo({'foo': 42,}) }} #output: 42

Display Array of data in Twig

I would like to display the following array of data in twig:
array:7
0 => []
1 => "Q4(2017)"
2 => "Q1(2018)"
3 => "Q2(2018)"
4 => "Q3(2018)"
5 => "Q4(2018)"
6 => "Q1(2019)"
]
I tried to display the above array of data in Symfony Twig as following but it returned error. Could you please advise?
{% for key, value in arrayList %}
<br>{{ value }}<br>
{% endfor %}
I expect the results as following but it returned errors
Q4(2017)
Q1(2018)
Q2(2018)
Q3(2018)
Q4(2018)
Q1(2019)
You don't need to pass key and value as parameters.
{% for value in arrayList %}
<br>{{ value }}<br>
{% endfor %}

Move if/then logic into view or model or keep in template?

after creating a web app using backbone for an engine design firm, I'm wondering if I should move the "if/then" logic out of the html templates.
To help clarify what I mean, here are two examples that I am currently using in production.
If I move the if/then logic out of the template, I would move it to the view, but I'm not sure if that's the "right" way or "backbone" way of doing things.
Am I making poor design decisions, or is what I've done OK?
Thanks!
Simple Example 1:
In the view:
//m is the model used by the view
return Backbone.View.extend({
template: _.template(tmpl, null, { variable: 'm' }),
In the template:
{% if(m.title) { %}
<h4> {%- m.title %} </h4>
{% } else { %}
<h4>Experiment Title Goes Here</h4>
{% } %}
Complex Example 2:
In the view:
//args are the model attributes passed into the view
initialize: function (args) {
this.currentEngine = args.currentEngine;
this.engineDisplay = args.engineDisplay;
this.engineType = args.engineType;
this.isCurrent = this.model.isCurrent(this.currentEngine);
},
render: function () {
this.$el.html(this.template({
engineDisplay: this.engineDisplay,
engineType: this.engineType,
isCurrent: this.isCurrent;
}));
In the template:
{% if(!engineDisplay) { %}
{% if (m.isCurrent && (engineType === 'GAS' || engineType === 'ECO')) { %}
<span>Not Available</span>
{% } else { %}
<span>
<span>Click here to select</span>
</span>
{% } %}
{% } %}
I think your first implementation was correct. Keep the logic out of the view. The "correct" way, or the "backbone" way is to keep the logic where it needs to be:
the model/collection houses code of "where" the data needs to come from.
the view houses code of "what" it needs to do/display. (what needs to happen if event X happens)
the template should house the code of "how" it needs to be displayed.
I'm sure im missing stuff.. i'll wait until the comments tells me how wrong i am and then i'll correct it.
-Sheers

How to display multiple data sets in Symfony2

I am totally new to Symfony and i d like to know how I manage to display multiple data sets from my db in a twig...
untill now my attempt is the following:
class ProjController extends Controller
{
/**
* #Route("/", name="_projekte")
* #Template("FHBingenBundle:projekte:list.html.twig")
*
*/
public function indexAction()
{
$projekte = $this->getDoctrine()
->getRepository('FHBingenBundle:Projekt')->findAll();
return $projekte;
}
}
to get all the data sets. Here is where my Problem starts... how do I extract the data from the array? (the entity has multiple columns but i only want two of them, name and description)
{% extends "FHBingenBundle::layout.html.twig" %}
{% block content %}
<table>
<?php foreach ($liste as $projekt ?>
<tr><p>{{ $projekt->getName() }}</p></tr>
<?php endforeach;?>
</table>
{% endblock %}
thats how I tried to do it but apperently I am not allowed to use $ inside of {{}}? atleast thats what the error says
You should consider reading the cookbook.
Since you are using twig, think about using twig templating system.
{% for item in navigation %} // equivalent to foreach($navigation as $item) {
{{ item.name }} // equivalent to $item->name or $item->getName() or $item->hasName()
{% endfor %} // equivalent to }
EDIT : I don't really remember but it seems that you have to return an array for the twig templating system. return array('projects' => $projects);

Change meta page titles on Big Cartel dynamically

I have a custom theme in Big Cartel and I need to create an if statement using BC's own tags that looks at the page URL and then displays a tag.
For example, if url is homepage show this tag, if it is product page a, show this tag and so on...
Anyone have any idea how I can write that?
At the moment the theme has this:
<title>{{ page.name | remove: '-footer-' | remove: '-hide-' | remove: '-sidebar-' | remove: '-subnav-' | remove: '-f1-' | remove: '-f2-' | remove: '-f3-' }} | {{ store.name }}</title>
There are a number of different conditions you could use for this, like checking the page name, page permalink, the full URL, or others. A full variable reference is available here: http://help.bigcartel.com/customer/portal/articles/772750-variables#page
Here's a couple examples:
{% if page.name == 'Home' %}code here {% endif %}
{% if page.permalink == 'home' %}
code here
{% elsif page.permalink == 'product' %}
more code here
{% endif %}

Resources