hide empty collection in / from menu in Shopify - collections

I recently moved from Woocommerce to Shopify. I am using Expanse theme from Shopify. I have set listings not to show once they sold out or no stock is available. I need help with hiding the collection from menu that has no stock. I am going to add the code below. Kindly help what code line i need to add within that code.
The header navigation liquid code is below;
{%- liquid
unless limit
assign limit = main_menu.links.size
endunless
unless offset
assign offset = 0
endunless
-%}
<ul class="site-nav site-navigation site-navigation--{{ nav_position }} small--hide" role="navigation">
{%- for link in main_menu.links limit: limit offset: offset -%}
{%- liquid
assign has_dropdown = false
assign is_megamenu = false
if link.levels > 0
assign has_dropdown = true
if link.levels > 1
assign is_megamenu = true
endif
endif
assign isCollection = false
if show_mega_products
if is_megamenu and link.url contains '/collections/'
assign lang_code_string = request.locale.iso_code | prepend: '/' | downcase
assign collection_handle = link.url | remove: '/collections/' | remove: lang_code_string
assign collection_drop = collections[collection_handle]
assign isCollection = true
endif
endif
-%}
<li
class="site-nav__item site-nav__expanded-item{% if has_dropdown %} site-nav--has-dropdown{% endif %}{% if is_megamenu %} site-nav--is-megamenu{% endif %}"
{% if has_dropdown %}aria-haspopup="true"{% endif %}>
<a href="{{ link.url }}" class="site-nav__link site-nav__link--underline{% if has_dropdown %} site-nav__link--has-dropdown{% endif %}">
{{ link.title }}
</a>
{%- if is_megamenu -%}
{%- assign previous_column_type = '' -%}
<div class="site-nav__dropdown megamenu text-left">
<div class="page-width">
<div class="site-nav__dropdown-animate megamenu__wrapper">
<div class="megamenu__cols">
<div class="megamenu__col">
{%- for childlink in link.links -%}
{%- liquid
assign create_new_column = false
if childlink.levels > 0 and forloop.index != 1
assign create_new_column = true
endif
if childlink.levels == 0 and previous_column_type == 'full'
assign create_new_column = true
endif
-%}
{%- if create_new_column -%}
</div><div class="megamenu__col">
{%- endif -%}
<div class="megamenu__col-title">
{{ childlink.title }}
</div>
{%- liquid
if childlink.levels > 0
assign previous_column_type = 'full'
else
assign previous_column_type = 'single'
endif
-%}
{%- for grandchildlink in childlink.links -%}
<a href="{{ grandchildlink.url }}" class="site-nav__dropdown-link">
{{grandchildlink.title}}
</a>
{%- endfor -%}
{%- endfor -%}
</div>
</div>
{%- if isCollection -%}
<div class="megamenu__featured">
<div class="product-grid">
{%- liquid
assign mega_product = collection_drop.products.first
render 'product-grid-item', product: mega_product
if settings.quick_shop_enable
render 'quick-shop-modal', product: mega_product
endif
-%}
</div>
</div>
{%- endif -%}
</div>
</div>
</div>
{%- elsif has_dropdown -%}
<div class="site-nav__dropdown">
<ul class="site-nav__dropdown-animate site-nav__dropdown-list text-left">
{%- for childlink in link.links -%}
{%- liquid
assign has_sub_dropdown = false
if childlink.levels > 0
assign has_sub_dropdown = true
endif
-%}
<li class="{% if has_sub_dropdown %} site-nav__deep-dropdown-trigger{% endif %}">
<a href="{{ childlink.url }}" class="site-nav__dropdown-link site-nav__dropdown-link--second-level{% if has_sub_dropdown %} site-nav__dropdown-link--has-children{% endif %}">
{{ childlink.title | escape }}
{%- if has_sub_dropdown -%}
<svg aria-hidden="true" focusable="false" role="presentation" class="icon icon--wide icon-chevron-down" viewBox="0 0 28 16"><path d="M1.57 1.59l12.76 12.77L27.1 1.59" stroke-width="2" stroke="#000" fill="none" fill-rule="evenodd"/></svg>
{%- endif -%}
</a>
{%- if has_sub_dropdown -%}
<ul class="site-nav__deep-dropdown">
{%- for grandchildlink in childlink.links -%}
<li>
{{ grandchildlink.title | escape }}
</li>
{%- endfor -%}
</ul>
{%- endif -%}
</li>
{%- endfor -%}
</ul>
</div>
{%- endif -%}
</li>
{%- endfor -%}
</ul>

Here is a way to check if a link object is a collection and if it contains or not available products (which I understand is your question) (not tested):
{% if link.type == 'collection_link' %}
{% assign c_products = link.object.products | where: "available" %}
{% if c_products.size > 0 %}
Display the link
{% endif %}
{% endif %}
Explanations:
First, I check if the current link is a link to a collection by checking type value.
If it is, I define an array of available products contained by the collection (accessing it via link.object) whith a filter. The where filter is here to keep only available products in the array.
Then I check if the array size, then I know whether collection contains available products or not.
HTH
Useful documentation :
Link object: https://shopify.dev/api/liquid/objects#link
Where filter (arrays): https://shopify.github.io/liquid/filters/where/
Size filter (arrays): https://shopify.github.io/liquid/filters/size/

Related

How to create a counter with TWIG?

I have a site with Drupal 8 and I want to create a task counter with TWIG.
I use views with conditions. The counter must be incremented whether the view has a result or not.
Here is the code I just made :
<span class="badge badge-warning task-badge-warning">
{% if drupal_view_result('boutique_page_liste_des_taches_produit_non_publie', 'block_1') is not empty %}
1
{% endif %}
{% if drupal_view_result('boutique_page_liste_des_taches_role_marchand', 'block_1') is empty %}
1
{% endif %}
</span>
<span class="badge badge-danger task-badge-danger">
{% if drupal_view_result('boutique_page_liste_des_taches_aucun_produit', 'block_1') is empty %}
1
{% endif %}
{% if drupal_view_result('boutique_page_liste_des_taches_aucune_variation', 'block_1') is not empty %}
1
{% endif %}
{% if drupal_view_result('boutique_page_liste_des_taches_commande', 'block_1') is not empty %}
1
{% endif %}
{% if drupal_view_result('boutique_page_liste_des_taches_mode_de_livraison', 'block_1') is empty %}
1
{% endif %}
{% if drupal_view_result('boutique_page_liste_des_taches_passerelle_de_paiement', 'block_1') is empty %}
1
{% endif %}
</span>
There are 2 counters :
a "Warning" badge
a "Danger" badge
Do you know a solution to do this ?
The "Warning" badge must display the total number of "Warning" tasks.
The "Danger" badge must display the total number of "Danger" tasks.
You can set variables and then increment them:
{% set warnings = 0 %}
<span class="badge badge-warning task-badge-warning">
{% if drupal_view_result('boutique_page_liste_des_taches_produit_non_publie', 'block_1') is not empty %}
{% set warnings = warnings + 1 %}
{% endif %}
{% if drupal_view_result('boutique_page_liste_des_taches_role_marchand', 'block_1') is empty %}
{% set warnings = warnings + 1 %}
{% endif %}
{{ warnings }}
</span>
{% set dangers = 0 %}
<span class="badge badge-danger task-badge-danger">
{% if drupal_view_result('boutique_page_liste_des_taches_aucun_produit', 'block_1') is empty %}
{% set dangers = dangers + 1 %}
{% endif %}
{% if drupal_view_result('boutique_page_liste_des_taches_aucune_variation', 'block_1') is not empty %}
{% set dangers = dangers + 1 %}
{% endif %}
{% if drupal_view_result('boutique_page_liste_des_taches_commande', 'block_1') is not empty %}
{% set dangers = dangers + 1 %}
{% endif %}
{% if drupal_view_result('boutique_page_liste_des_taches_mode_de_livraison', 'block_1') is empty %}
{% set dangers = dangers + 1 %}
{% endif %}
{% if drupal_view_result('boutique_page_liste_des_taches_passerelle_de_paiement', 'block_1') is empty %}
{% set dangers = dangers + 1 %}
{% endif %}
{{ dangers }}
</span>

KnpMenuBundle not working with Bootstrap 4 navbar

I am currently making a menu with the Symfony bundle: KnpMenuBundle. I am using Bootstrap 4 as stylesheet.
Bootstrap 4 requires each list item in the navbar to have the class 'nav-item':
<li class="nav-item active"> <-- this
<a class="nav-link" href="#">Home <span class="sr-only">(current)</span></a>
</li>
I can't seem to figure out how to add the class 'nav-item' to the list item with KnpMenuBundle. Currently I see this when I load the page:
navbar result
This is my Builder class in src/AppBundle/Menu:
namespace AppBundle\Menu;
use Knp\Menu\MenuFactory;
class Builder
{
public function mainMenu(MenuFactory $factory, array $optioins)
{
$menu = $factory->createItem('root');
$menu->setChildrenAttribute('class', 'navbar-nav mr-auto');
$menu->addChild('Home', ['route' => 'homepage']);
$menu->setChildrenAttributes(['class' => 'nav-item']);
return $menu;
}
}
My code in base.html.twig to generate menu:
{{ knp_menu_render('AppBundle:Builder:mainMenu', {'currentClass': 'active'}) }}
What do I do to make it working?
I did this to get top level correct. Haven't worked out dropdowns yet though.
$menu->setChildrenAttribute('class', 'navbar-nav');
// menu items
foreach ($menu as $child) {
$child->setLinkAttribute('class', 'nav-link')
->setAttribute('class', 'nav-item');
}
You can add a class to each child items when you add it like that:
$menu->addChild('Home', ['route' => 'homepage'])
->setAttributes(array(
'class' => 'nav-item'
));
You should create new template file, for example "extended_knp_menu.html.twig" (also filename should not be named knp_menu.html.twig), with contents (src):
{% extends 'knp_menu.html.twig' %}
{% macro setCssClassAttribute(item, type, add) %}
{% set getter = 'get' ~ type %}
{% set setter = 'set' ~ type %}
{% set value = attribute(item, getter, ['class']) %}
{% if value is iterable %}
{% set value = value|join(' ') %}
{% endif %}
{% do attribute(item, setter, ['class', value ~ ' ' ~ add]) %}
{% endmacro %}
{% block item %}
{% import "knp_menu.html.twig" as macros %}
{#
As multiple level is not currently supported by bootstrap 4
This requires you to install
https://github.com/bootstrapthemesco/bootstrap-4-multi-dropdown-navbar
And set the the use_multilevel = true
#}
{% set use_multilevel = false %}
{% if item.displayed %}
{%- set attributes = item.attributes %}
{%- set is_dropdown = attributes.dropdown|default(false) %}
{%- set divider_prepend = attributes.divider_prepend|default(false) %}
{%- set divider_append = attributes.divider_append|default(false) %}
{# unset bootstrap specific attributes #}
{%- set attributes = attributes|merge({'dropdown': null, 'divider_prepend': null, 'divider_append': null }) %}
{%- if divider_prepend %}
{{ block('dividerElement') }}
{%- endif %}
{# building the class of the item #}
{%- set classes = item.attribute('class') is not empty ? [item.attribute('class'), 'nav-item'] : ['nav-item'] %}
{%- if matcher.isCurrent(item) %}
{%- set classes = classes|merge([options.currentClass]) %}
{%- elseif matcher.isAncestor(item, options.depth) %}
{%- set classes = classes|merge([options.ancestorClass]) %}
{%- endif %}
{%- if item.actsLikeFirst %}
{%- set classes = classes|merge([options.firstClass]) %}
{%- endif %}
{%- if item.actsLikeLast %}
{%- set classes = classes|merge([options.lastClass]) %}
{%- endif %}
{# building the class of the children #}
{%- set childrenClasses = item.childrenAttribute('class') is not empty ? [item.childrenAttribute('class')] : [] %}
{%- set childrenClasses = childrenClasses|merge(['menu_level_' ~ item.level]) %}
{# adding classes for dropdown #}
{%- if is_dropdown %}
{%- set classes = classes|merge(['dropdown']) %}
{%- set childrenClasses = childrenClasses|merge(['dropdown-menu']) %}
{%- endif %}
{# putting classes together #}
{%- if classes is not empty %}
{%- set attributes = attributes|merge({'class': classes|join(' ')}) %}
{%- endif %}
{%- set listAttributes = item.childrenAttributes|merge({'class': childrenClasses|join(' ') }) %}
<li{{ macros.attributes(attributes) }}>
{# displaying the item #}
{%- if is_dropdown %}
{{ block('dropdownElement') }}
{%- elseif item.uri is not empty and (not item.current or options.currentAsLink) %}
{{ block('linkElement') }}
{%- else %}
{{ block('spanElement') }}
{%- endif %}
{%- if divider_append %}
{{ block('dividerElement') }}
{%- endif %}
{% if item.hasChildren and options.depth is not same as(0) and item.displayChildren %}
{{ block('dropdownlinks') }}
{% endif %}
</li>
{% endif %}
{% endblock %}
{% block dropdownlinks %}
{% if use_multilevel %}
<ul class="dropdown-menu">
{% else %}
<div class="dropdown-menu">
{% endif %}
{% for item in item.children %}
{{ block('renderDropdownlink') }}
{% if use_multilevel and item.hasChildren and options.depth is not same as(0) and item.displayChildren %}
{{ block('dropdownlinks') }}
{% endif %}
{% endfor %}
{% if not use_multilevel %}
</div>
{% else %}
</ul>
{% endif %}
{% endblock %}
{% block renderDropdownlink %}
{% import _self as ownmacro %}
{%- set divider_prepend = item.attributes.divider_prepend|default(false) %}
{%- set divider_append = item.attributes.divider_append|default(false) %}
{%- set attributes = item.attributes|merge({'dropdown': null, 'divider_prepend': null, 'divider_append': null }) %}
{% if use_multilevel %}
<li>
{% endif %}
{%- if divider_prepend %}
{{ block('dividerElementDropdown') }}
{%- endif %}
{%- if item.uri is not empty and (not item.current or options.currentAsLink) %}
{{ ownmacro.setCssClassAttribute(item, 'LinkAttribute', 'dropdown-item') }}
{{ block('linkElement') }}
{%- else %}
{{ block('spanElementDropdown') }}
{%- endif %}
{%- if divider_append %}
{{ block('dividerElementDropdown') }}
{%- endif %}
{% if use_multilevel %}
</li>
{% endif %}
{% endblock %}
{% block spanElementDropdown %}
{% import "knp_menu.html.twig" as macros %}
{% import _self as ownmacro %}
{{ ownmacro.setCssClassAttribute(item, 'LabelAttribute', 'dropdown-header') }}
<div {{ macros.attributes(item.labelAttributes) }}>
{% if item.attribute('icon') is not empty %}
<i class="{{ item.attribute('icon') }}"></i>
{% endif %}
{{ block('label') }}
</div>
{% endblock %}
{% block dividerElementDropdown %}
<div class="dropdown-divider"></div>
{% endblock %}
{% block dividerElement %}
{% if item.level == 1 %}
<li class="divider-vertical"></li>
{% else %}
<li class="divider"></li>
{% endif %}
{% endblock %}
{% block linkElement %}
{% import "knp_menu.html.twig" as macros %}
{% import _self as ownmacro %}
{{ ownmacro.setCssClassAttribute(item, 'LinkAttribute', 'nav-link') }}
<a href="{{ item.uri }}"{{ macros.attributes(item.linkAttributes) }}>
{% if item.attribute('icon') is not empty %}
<i class="{{ item.attribute('icon') }}"></i>
{% endif %}
{{ block('label') }}
</a>
{% endblock %}
{% block spanElement %}
{% import "knp_menu.html.twig" as macros %}
{% import _self as ownmacro %}
{{ ownmacro.setCssClassAttribute(item, 'LabelAttribute', 'navbar-text') }}
<span {{ macros.attributes(item.labelAttributes) }}>
{% if item.attribute('icon') is not empty %}
<i class="{{ item.attribute('icon') }}"></i>
{% endif %}
{{ block('label') }}
</span>
{% endblock %}
{% block dropdownElement %}
{% import "knp_menu.html.twig" as macros %}
{%- set classes = item.linkAttribute('class') is not empty ? [item.linkAttribute('class')] : [] %}
{%- set classes = classes|merge(['dropdown-toggle', 'nav-link']) %}
{%- set attributes = item.linkAttributes %}
{%- set attributes = attributes|merge({'class': classes|join(' ')}) %}
{%- set attributes = attributes|merge({'data-toggle': 'dropdown'}) %}
<a href="#"{{ macros.attributes(attributes) }}>
{% if item.attribute('icon') is not empty %}
<i class="{{ item.attribute('icon') }}"></i>
{% endif %}
{{ block('label') }}
<b class="caret"></b>
</a>
{% endblock %}
{% block label %}{{ item.label|trans }}{% endblock %}
After just include rendering template for menu:
{{ knp_menu_render('AppBundle:Builder:mainMenu', {
'currentClass': 'active',
'template': 'extended_knp_menu.html.twig'
}) }}
Hope it helped you.

KnpMenuBundle add icon/glyphicon

I have tried to set an icon next to the link of the menu generated by knpMenuBundle but no way to get it.
I found some solutions like ->setAttribute or ->setExtra, but I can't make it work.
Do I have to add specific lines to the base template of knp ?
Do something special in the twig render ?
Here is what I have tried so far:
//Builder.php
$public function mainMenu(FactoryInterface $factory, array $options)
{
$menu = $factory->createItem('root');
$menu->setChildrenAttribute('class', 'nav navbar-nav ');
$menu->addChild('Mes Informations',['route' => 'espace_client_mesInformations'])
->setAttribute('icon','fa fa-home');
$menu->addChild('Mes Factures', array('route' => 'espace_client_mesFactures'));
$menu->addChild('Mon Extrait de Compte', array('route' => 'espace_client_mesReglements'));
$menu->addChild('Mes Services', array('route' => 'espace_client_mesServices'));
$menu->addChild('Mes Consommations', array('route' => 'espace_client_mesConsommations'));
$menu['Mes Consommations']->addChild('Télephone', array('route' => 'espace_client_mesConsoTelephone'));
$menu['Mes Consommations']->addChild('Internet', array('route' => 'espace_client_mesConsoInternet'));
$menu->addChild('Mes Liens Directs', array('route' => 'espace_client_mesLiens'));
return $menu;
}
//menu.html.twig
<div class="panel panel-default">
<div class="panel-heading">
<center><h4> Menu </h4></center>
</div>
<div class="panel-body">
{{ knp_menu_render('EspaceClientBundle:Builder:mainMenu',{'currentAsLink':false, 'template': 'EspaceClientBundle:Menu:knp_menu.html.twig'}) }}
</div>
If anyone have an answer ?
Thanks.
Edit:
I'm a little bit confused by the different files of the bundle, I must have a problem in my php code so there is the content of them:
//knp_menu.html.twig:
{% extends 'knp_menu_base.html.twig' %}
{% macro attributes(attributes) %}
{% for name, value in attributes %}
{%- if value is not none and value is not same as(false) -%}
{{- ' %s="%s"'|format(name, value is same as(true) ? name|e : value|e)|raw -}}
{%- endif -%}
{%- endfor -%}
{% endmacro %}
{% block compressed_root %}
{% spaceless %}
{{ block('root') }}
{% endspaceless %}
{% endblock %}
{% block root %}
{% set listAttributes = item.childrenAttributes %}
{{ block('list') -}}
{% endblock %}
{% block list %}
{% if item.hasChildren and options.depth is not same as(0) and item.displayChildren %}
{% import _self as knp_menu %}
<ul{{ knp_menu.attributes(listAttributes) }}>
{{ block('children') }}
</ul>
{% endif %}
{% endblock %}
{% block children %}
{# save current variables #}
{% set currentOptions = options %}
{% set currentItem = item %}
{# update the depth for children #}
{% if options.depth is not none %}
{% set options = options|merge({'depth': currentOptions.depth - 1}) %}
{% endif %}
{# update the matchingDepth for children #}
{% if options.matchingDepth is not none and options.matchingDepth > 0 %}
{% set options = options|merge({'matchingDepth': currentOptions.matchingDepth - 1}) %}
{% endif %}
{% for item in currentItem.children %}
{{ block('item') }}
{% endfor %}
{# restore current variables #}
{% set item = currentItem %}
{% set options = currentOptions %}
{% endblock %}
{% block item %}
{% if item.displayed %}
{# building the class of the item #}
{%- set classes = item.attribute('class') is not empty ? [item.attribute('class')] : [] %}
{%- if matcher.isCurrent(item) %}
{%- set classes = classes|merge([options.currentClass]) %}
{%- elseif matcher.isAncestor(item, options.matchingDepth) %}
{%- set classes = classes|merge([options.ancestorClass]) %}
{%- endif %}
{%- if item.actsLikeFirst %}
{%- set classes = classes|merge([options.firstClass]) %}
{%- endif %}
{%- if item.actsLikeLast %}
{%- set classes = classes|merge([options.lastClass]) %}
{%- endif %}
{# Mark item as "leaf" (no children) or as "branch" (has children that are displayed) #}
{% if item.hasChildren and options.depth is not same as(0) %}
{% if options.branch_class is not empty and item.displayChildren %}
{%- set classes = classes|merge([options.branch_class]) %}
{% endif %}
{% elseif options.leaf_class is not empty %}
{%- set classes = classes|merge([options.leaf_class]) %}
{%- endif %}
{%- set attributes = item.attributes %}
{%- if classes is not empty %}
{%- set attributes = attributes|merge({'class': classes|join(' ')}) %}
{%- endif %}
{# displaying the item #}
{% import _self as knp_menu %}
<li{{ knp_menu.attributes(attributes) }}>
{%- if item.uri is not empty and (not matcher.isCurrent(item) or options.currentAsLink) %}
{{ block('linkElement') }}
{%- else %}
{{ block('spanElement') }}
{%- endif %}
{# render the list of children#}
{%- set childrenClasses = item.childrenAttribute('class') is not empty ? [item.childrenAttribute('class')] : [] %}
{%- set childrenClasses = childrenClasses|merge(['menu_level_' ~ item.level]) %}
{%- set listAttributes = item.childrenAttributes|merge({'class': childrenClasses|join(' ') }) %}
{{ block('list') }}
</li>
{% endif %}
{% endblock %}
{% block linkElement %}
{% import "knp_menu.html.twig" as macros %}
<a href="{{ item.uri }}"{{ macros.attributes(item.linkAttributes) }}>
<span class="icon">{{ item.getExtra('icon') }}</span>
<span class="entry">{{ block('label') }}</span>
</a>
{% endblock %}
{% block spanElement %}{% import _self as knp_menu %}<span{{ knp_menu.attributes(item.labelAttributes) }}>{{ block('label') }}</span>{% endblock %}
You should edit your menu template EspaceClientBundle:Menu:knp_menu.html.twig like:
{% block label %}
{% if options.allow_safe_labels and item.getExtra('safe_label', false) %}
{{ item.label|raw|trans }}
{% else %}
{{ item.label }}
{% endif %}
{% if item.extras.icon is defined %}
<i class="{{ item.extras.icon }}"></i>
{% endif %}
{% endblock %}
I recommend you, to delete the whitespaces between twig tags.
Then, in menu builder:
$menu->addChild('Mes Informations', [
'route' => 'espace_client_mesInformations',
'extras' => ['icon' => 'fa fa-home']
]);

jinja2: How to properly format a recursive macro

I have a nested structure and a recursive macro to render it. however there is an extra empty line before all of the closing tags. How do I remove the empty lines so that is renders one contiguous block?
The data is in a form like so
name='...'
list
a
a
b
name='...'
list
b
b
a
The template is like so
{% macro list(item) -%}
<ul name="{{ item.name }}">
{% for item in item.list -%}
{% if item.a -%}
<li a="{{ item.a }}"/>
{% elif item.b -%}
<li b="{{ item.a }}">
{% item.name -%}
{{- list(item) }}
{% endif -%}
{%- endfor %}
</ul>
{% endmacro -%}
The expected outcome shouldn't have this extra whitespace before the </ul>.
<ul name="...">
<li a="a"/>
<li a="a"/>
<li b="b"/>
<ul name="...">
<li b="b"/>
<li b="b"/>
</ul>
<li a="a"/>
</ul>
Since Jinja is keeping track of linespacing why not move the statements to one line for the ending of "if" and "for" jinja declarations?
{% macro list(item) -%}
<ul name="{{ item.name }}">
{% for item in item.list -%}
{% if item.a -%}
<li a="{{ item.a }}"/>
{% elif item.b -%}
<li b="{{ item.a }}">
{% item.name -%}
{{- list(item) }}{% endif -%}{%- endfor %}
</ul>
{% endmacro -%}

Symfony2 form entity style each option differently (collapse)

I have an entity field (visitors) in a form. I would like to highlight a person according to its status.
->add('visitors', 'entity', array(
'class' => "T2m3Bundle:Person",
'multiple' => true,
'property' => 'entireName',
'required' => false,
)
I have a method getStatus, that returns 4 states. On every state I want to put different "style" in an option tag.
Here is the example:
<select>
<option value="1">Mary</option>
<option value="2" class="alert alert-danger">John</option>
<option value="3" class="alert alert-success">Peter</option>
<option value="4" class="alert alert-warning">Robert</option>
</select>
So I want to do something like this:
{% for visitor in form.visitors %}
{% set index = visitor.vars.value %}
{% set entity = form.visitors.vars.choices[index].data %}
{% if entity.status == 1 %}
{{ form_widget(visitor) }}
<span class="alert alert-warning">{{ entity.entireName }}</span>
{% endif %}
{% if entity.status == 2 %}
{{ form_widget(visitor) }}
<span class="alert alert-danger">{{ entity.entireName }}</span>
{% endif %}
....
{% endfor %}
This example works for 'expanded' => true but not for collapse type. I would be really thankful for an answer.
Thanks in advance!
EDIT:
Expanded use this template with form_widget(...):
{% block choice_widget_expanded -%}
<div {{ block('widget_container_attributes') }}>
{%- for child in form %}
{{- form_widget(child) -}}
{{- form_label(child) -}}
{% endfor -%}
</div>
{% endblock choice_widget_expanded %}
but I don't know how to render manually collapsed type, where there is no {{- form_widget(...) -}}
Try to override the twig choice widget : refer to this link to find the according block. It's something like this
{% block choice_widget_collapsed -%}
{% if required and placeholder is none and not placeholder_in_choices and not multiple -%}
{% set required = false %}
{%- endif -%}
<select {{ block('widget_attributes') }}{% if multiple %} multiple="multiple"{% endif %}>
{% if placeholder is not none -%}
<option value=""{% if required and value is empty %} selected="selected"{% endif %}>{{ placeholder|trans({}, translation_domain) }}</option>
{%- endif %}
{%- if preferred_choices|length > 0 -%}
{% set options = preferred_choices %}
{{- block('choice_widget_options') -}}
{% if choices|length > 0 and separator is not none -%}
<option disabled="disabled">{{ separator }}</option>
{%- endif %}
{%- endif -%}
{% set options = choices -%}
{{- block('choice_widget_options') -}}
</select>
{%- endblock choice_widget_collapsed %}
{% block choice_widget_options -%}
{% for group_label, choice in options %}
{%- if choice is iterable -%}
<optgroup label="{{ group_label|trans({}, translation_domain) }}">
{% set options = choice %}
{{- block('choice_widget_options') -}}
</optgroup>
{%- else -%}
{# HERE we define the class based on the status #}
{% if status is defined %}
{% if status == 1 %}
{% set status_class = 'alert alert-warning' %}
{% elseif status == 2 %}
{% set status_class = 'alert alert-danger' %}
{% elseif ... %}
....
{% endif %}
{% endif %}
<option value="{{ choice.value }}"{% if choice is selectedchoice(value) %} selected="selected"{% endif %} {% if status_class is defined %} class="{{ status_class }}" {% endif %} >{{ choice.label|trans({}, translation_domain) }}</option>
{%- endif -%}
{% endfor %}
{%- endblock choice_widget_options %}
Finally in your template, call the widget like this :
{% for visitor in form.visitors %}
{% set index = visitor.vars.value %}
{% set entity = form.visitors.vars.choices[index].data %}
{{ form_widget(visitor, {'status': entity.status}) }}
....
{% endfor %}
This is not tested, but should work. Let me know.

Resources