Symfony Twig override specific form row - php

I have the a form twig template, where I want to parse a specific fields help text with the raw filter (it contains html). The field is called postcode in a form called Clinic
According to here http://symfony.com/doc/current/cookbook/form/form_customization.html#how-to-customize-an-individual-field
Form template:
{% extends 'AgriHealthAhpBundle::admin.html.twig' %}
{% form_theme form 'AgriHealthAhpBundle:Form:fields.html.twig' %}
{% block _clinic_postcode_row %}
<div class="row">
test<div class="small-12 medium-3 columns label">{{ form_label(form) }}</div>
<div class="small-12 medium-6 columns widget">
{{ form_widget(form) }}
<div class="error">
{{ form_errors(form) }}
</div>
</div>
<div class="small-12 medium-3 columns help">
{% if help is defined %}
{{ help|raw }}
{% endif %}
</div>
</div>
{% endblock %}
{% block admin -%}
<h1>New Clinic</h1>
{{ form(form) }}
<div class="row form_actions">
<div class="small-12 medium-offset-3 medium-2 columns submit">
<button type="submit" id="agrihealth_ahpbundle_clinic_submit_visible" name="agrihealth_ahpbundle_clinic[submit]">Create</button>
</div>
<script type="text/javascript">
jQuery(document).ready(function() {
jQuery('#agrihealth_ahpbundle_clinic_submit_visible').click(function(){
jQuery('form[name="agrihealth_ahpbundle_clinic"]').submit();
});
});
</script>
<div class="small-12 medium-2 columns cancel">
<a href="{{ path('clinic') }}">
Cancel
</a>
</div>
<div class="small-12 medium-2 end columns cancel">
<a href="{{ path('clinic') }}">
Back to List
</a>
</div>
</div>
{% endblock %}
AhpBundle/Resources/views/Form/fields.html.twig
{% block form_row %}
{% spaceless %}
<div class="row">
<div class="small-12 medium-3 columns label">{{ form_label(form) }}</div>
<div class="small-12 medium-6 columns widget">
{{ form_widget(form) }}
<div class="error">
{{ form_errors(form) }}
</div>
</div>
<div class="small-12 medium-3 columns help">
{% if help is defined %}
{{ help }}
{% endif %}
</div>
</div>
{% endspaceless %}
{% endblock form_row %}
Anyone can see what I have overlooked, I tried
{% block _clinic_postcode_row %}
and
{% block _Clinic_postcode_row %}
Solution
As per accepted answer, the form row block needs to fully idetified with shorthand bundle name. The easiest way is to view the source code of the form and identify the text used in each input field and the form name="":

Replace
{% form_theme form 'AgriHealthAhpBundle:Form:fields.html.twig' %}
with
{% form_theme form with ['AgriHealthAhpBundle:Form:fields.html.twig', _self] %}
Since you are decorating the row inside action template, while applying separate form template you need to specify multiple templates
You also need to specify a fully qualified path name to your row block such as
{% block _agrihealth_ahpbundle_clinic_postcode_row %}

Related

Twig how to check which template is geting rendered

I have
<div>
<div id="page-wrapper" class="sidebar-content white-bg">
<div class="row border-bottom">
{% include '/layouts/navbar.html.twig' %}
</div>
{% block body %}{% endblock %}
</div>
</div>
Now in this /layouts/navbar.html.twig theres an anchor tag, who's href attribute heavily depends on which template is rendered below, for example if its the Posts template, the href should be /posts/new, if its the announcements template, the href should be /announcements/newand so on, is that even possible?
You could make use of the global variable _self to solve this e.g.
main.twig
{% include "foo.twig" %}
{% include "bar.twig" %}
foo.twig and bar.twig
<div>
<div id="page-wrapper" class="sidebar-content white-bg">
<div class="row border-bottom">
{% include "nav.twig" with { 'template': _self, } %}
</div>
{% block body %}{% endblock %}
</div>
</div>
nav.twig
{% set path = '' %}
{% if template == 'foo.twig' %}
{% set path = 'path/to/foo' %}
{% elseif template == 'bar.twig' %}
{% set path = 'path/to/bar' %}
{% endif %}
{% for i in 0..3 %}
{{ i }}
{% endfor %}
demo
If the path is the only thing that depends on the current template, I'd modify DarkBee's example to just simply pass the path from the parent template. That way you don't need the if/else structure:
posts.twig:
<div>
<div id="page-wrapper" class="sidebar-content white-bg">
<div class="row border-bottom">
{% include "nav.twig" with { 'path': '/posts/new' } %}
</div>
{% block body %}{% endblock %}
</div>
</div>
announcements.twig:
<div>
<div id="page-wrapper" class="sidebar-content white-bg">
<div class="row border-bottom">
{% include "nav.twig" with { 'path': '/announcements/new' } %}
</div>
{% block body %}{% endblock %}
</div>
</div>
nav.twig:
{% for i in 0..3 %}
{{ i }}
{% endfor %}

Customer Order Email - How to display thumbnail of image upload by customer on email?

Basically in their shopping cart I would like to display the image they upload to print but i can't seem to figure it out..... I know i need to add in something along the lines of <img src="http://path/to/thumbnails/myimage.jpg"> but i don't know what to add in place of "http://path/to/thumbnails/myimage.jpg" within this code to display the image they upload if there even is anything? All help appreciated! Thanks (sorry if this is a silly question and plain obvious)
{% comment %}
This is your /cart template. If you are using the Ajaxify Cart plugin,
your form (with action="/cart") layout will be used in the drawer/modal.
For info on test orders:
- General http://docs.shopify.com/manual/your-store/orders/test-orders
- Shopify Payments - http://docs.shopify.com/manual/more/shopify-payments/testing-shopify-payments
<!-- Bold: Options 4-1 -->
<script>function update_qty_builder(builder_id, qty){ jQuery('.'+builder_id+"_qty").val(qty.value); } function remove_product_builder(builder_id){ jQuery('.'+builder_id+"_qty").val(0); jQuery('.'+builder_id+"_qty").parents("form").submit(); }</script>
{% include 'bold-cart-handler' %}
<!-- // end Options 4-1 -->
{% endcomment %}
{% if cart.item_count > 0 %}
<form action="/cart" method="post" novalidate class="cart">
<div class="section-header">
<h1 class="section-header__title">{{ 'cart.general.title' | t }}</h1>
</div>
<div class="cart__row medium-down--hide cart__header-labels">
<div class="grid--full">
<div class="grid__item large--one-half push--large--one-half">
<div class="grid--full">
<div class="grid__item one-third medium-down--one-third">
<span class="h4">{{ 'cart.label.price' | t }}</span>
</div>
<div class="grid__item one-third medium-down--one-third text-center">
<span class="h4">{{ 'cart.label.quantity' | t }}</span>
</div>
<div class="grid__item one-third medium-down--one-third text-right">
<span class="h4">{{ 'cart.label.total' | t }}</span>
</div>
</div>
</div>
</div>
</div>
{% comment %}
Loop through products in the cart
{% endcomment %}
{% for item in cart.items %}
<!-- Bold: Options 4-2 -->
{% include 'boldoptions' with 'step2' %}
<!-- // end Options 4-2 -->
<tr style="{% include 'boldoptions' with 'step4' %}" class="{% include 'boldoptions' with 'step3' %}">
<div class="cart__row" data-id="{{ item.id }}">
<div class="grid--full cart__row--table-large">
<div class="grid__item large--one-half">
<div class="grid">
<div class="grid__item one-third">
<a href="{{ item.url | within: collections.all }}" class="cart__image">
{% comment %}
More image size options at:
- http://docs.shopify.com/themes/filters/product-img-url
{% endcomment %}
<!-- Bold: Options 4-5 -->
{% if builder[0] %}
<img src="{{ builder[1] }}" alt="{{ builder[0] }}" />
{% else %}
<img src="{{ item | img_url: 'medium' }}" alt="{{ item.title | escape }}">
</a>
<!-- Bold: Options 4-6 -->
{% include 'boldoptions' with 'step6' %}
<!-- // end Options 4-6 -->
{% endif %}
<!-- // end Options 4-5 -->
</div>
<div class="grid__item two-thirds">
<a href="{{ item.url }}" class="h4">
{{ item.product.title }}
</a>
{% unless item.variant.title contains 'Default' %}
<br>
<small>{{ item.variant.title }}</small>
{% endunless %}
{% if settings.cart_vendor_enable %}
<p>{{ item.vendor }}</p>
{% endif %}
{% comment %}
Optional, loop through custom product line items if available
For more info on line item properties, visit:
- http://docs.shopify.com/support/your-store/products/how-do-I-collect-additional-information-on-the-product-page-Like-for-a-monogram-engraving-or-customization
{% endcomment %}
{% include 'product_customizer_cart' %}
{% if item.properties.size > 0 %}
{% for p in item.properties %}
{% unless p.last == blank %}
{{ p.first }}:
{% comment %}
Check if there was an uploaded file associated
{% endcomment %}
{% if p.last contains '/uploads/' %}
{{ p.last | split: '/' | last }}
{% else %}
{{ p.last }}
{% endif %}
<br>
{% endunless %}
{% endfor %}
{% endif %}
<a href="{% include 'boldoptions' with 'step9' %}" data-id="{{ item.id }}" class="{% include 'boldoptions' with 'step10' %} cart__remove" {% include 'boldoptions' with 'step11' %}>
<small>{{ 'cart.general.remove' | t }}</small>
</a>
</div>
</div>
</div>
<div class="grid__item large--one-half">
<div class="grid--full cart__row--table-large">
<div class="grid__item one-third">
<span class="cart__mini-labels">{{ 'cart.label.price' | t }}</span>
<span class="h5">{% include 'boldoptions' with 'step12' %}</span>
</div>
<div class="grid__item one-third text-center">
<span class="cart__mini-labels">{{ 'cart.label.quantity' | t }}</span>
{% comment %}
Added data-id for the ajax cart implementation only.
{% endcomment %}
<input type="number" name="updates[]" id="updates_{{ item.id }}" class="{% include 'boldoptions' with 'step7' %}" value="{{ item.quantity }}" min="0" data-id="{{ item.id }}" {% include 'boldoptions' with 'step8' %}>
</div>
<div class="grid__item one-third text-right">
<span class="cart__mini-labels">{{ 'cart.label.total' | t }}</span>
<span class="h5">{% include 'boldoptions' with 'step13' %}</span>
</div>
</div>
</div>
</div>
</div>
{% endfor %}
<div class="cart__row">
<div class="grid">
{% comment %}
Optional, add a textarea for special notes
- Your theme settings can turn this on or off. Default is on.
- Make sure you have name="note" for the message to be submitted properly
{% endcomment %}
{% if settings.cart_notes_enable %}
{% assign noteSize = cart.note | size %}
<div class="grid__item large--five-twelfths">
<button type="button" class="text-link cart__note-add{% if noteSize > 0 %} is-hidden{% endif %}">
{{ 'cart.label.add_note' | t }}
</button>
<div class="cart__note{% if noteSize > 0 %} is-active{% endif %}">
<label for="CartSpecialInstructions">{{ 'cart.general.note' | t }}</label>
<textarea name="note" class="input-full" id="CartSpecialInstructions">{{ cart.note }}</textarea>
</div>
</div>
{% endif %}
<div class="grid__item text-right{% if settings.cart_notes_enable %} large--seven-twelfths{% endif %}">
<p>
<span class="cart__subtotal-title">{{ 'cart.general.subtotal' | t }}</span>
<span class="h5 cart__subtotal">{{ cart.total_price | money }}</span>
</p>
<p><em>{{ 'cart.general.shipping_at_checkout' | t }}</em></p>
<input type="submit" name="update" class="btn--secondary update-cart" value="{{ 'cart.general.update' | t }}">
<input type="submit" name="checkout" class="btn" value="{{ 'cart.general.checkout' | t }}">
{% if additional_checkout_buttons %}
<div class="cart__additional_checkout">{{ content_for_additional_checkout_buttons }}</div>
{% endif %}
</div>
</div>
</div>
</form>
{% else %}
{% comment %}
The cart is empty
{% endcomment %}
<h2>{{ 'cart.general.title' | t }}</h2>
<p>{{ 'cart.general.empty' | t }}</p>
<p>{{ 'cart.general.continue_browsing_html' | t }}</p>
{% endif %}
<!-- Bold: Options 4-14 -->
{% include 'bold-cart-modal' %}
<!-- // end Options 4-14 -->
You have to include the full publicly reachable image path in the src attribute of the image tag
<img src="http://path/to/thumbnails/myimage.jpg">

Customize embedded form symfony 2

I have read the Symfony 2 documentation and I'm trying to make a custom embedded form and I can't understand the provided code in the documentation.
Official documentation:
http://symfony.com/doc/current/cookbook/form/form_customization.html
Specifically the code that i don't understand is this:
{% form_theme form _self %}
{% block _tasks_entry_widget %}
<tr>
<td>{{ form_widget(task.task) }}</td>
<td>{{ form_widget(task.dueDate) }}</td>
</tr>
{% endblock %}
after many tests I've noticed that '_task_entry' is the name of the embedded form (not the name of field in the main form)
Now I'm trying to get what is the 'task' variable, {{ form_widget(task.dueDate) }}
I've tried with the embedded form name again, with the name of the entity field, and with the name of the main form variable but nothing works:
{% form_theme edit_form.lineas _self %}
{% block zb_gestionbundle_lineaalbaran_widget %}
<div class="large-1 small-1 columns">
{{ form_widget(form.cantidad) }}
</div>
<div class="large-8 small-8 columns">
{{ form_widget(form.concepto) }}
</div>
<div class="large-2 small-2 columns">
{{ form_widget(form.precio) }}
</div>
{% endblock %}
{{ form_label(edit_form.lineas) }}
{{ form_errors(edit_form.lineas) }}
{{ form_widget(edit_form.lineas) }}
In summary, What I need to put in {{ form_widget(form.cantidad) }} for make the code works?
Tyvm!!
One possible solution:
After investigate a little more, I've found this code that works!
{% form_theme edit_form _self %}
{% macro prototype(linea) %}
<div class="large-1 small-1 columns">
{{ form_widget(linea.cantidad) }}
</div>
<div class="large-8 small-8 columns">
{{ form_widget(linea.concepto) }}
</div>
<div class="large-2 small-2 columns">
{{ form_widget(linea.precio) }}
</div>
{% endmacro %}
{% for linea in edit_form.lineas %}
{{_self.prototype(linea)}}
{% endfor %}
I don't know if the documentation is wrong, I leave the answer open for the doubt about the documentation.
Your solution work ! Just to complete, i had the same problem but the documentation is correct ! Just a little bit difficult to understand.(in my opinion).
To use the documentation solution :
you have to know the unique_block_prefix of your embbeded form.
To do this : add this to your code {{dump(form)}} and search the unique_block_prefix of your embedded form.
then you just have to replace the example of documentation like this :
{% form_theme form _self %}
{% block _zb_gestionbundle_lineaalbaran_entry_widget %}
<div class="large-1 small-1 columns">
{{ form_widget(form.cantidad) }}
</div>
<div class="large-8 small-8 columns">
{{ form_widget(form.concepto) }}
</div>
<div class="large-2 small-2 columns">
{{ form_widget(form.precio) }}
</div>
{% endblock %}
<!--block with your html/twig code, form, etc ..-->
{% block your_main_block %}
...
<!--your form-->
...
<!-- the embbeded part -->
{{form_row(form.lineas)}}
...
{% endblock %}
To sum up, generally the unique_block_prefix is
_(id of your embedded form)_entry_widget
And you just have to replace like the example of the doc.
I hope you understand and i miss nothing(sorry for my english...).

Variable does not exist twig symfony

I have a controller that does this
/**
* #Route("/AjaxAddQuestionForm/{section}")
* #ParamConverter("section", class="AppBundle:Section")
*/
public function ajaxAddQuestionFormAction(Request $request, $section)
{
$question = new Question();
$addQuestionForm = $this->createForm(new AddQuestionType(), $question);
return $this->render('AppBundle:Form:ajaxAddQuestionForm.html.twig', array(
'section' => $section,
'addAjaxQuestionForm' => $addQuestionForm->createView(),
));
}
The ajaxAddQuestionForm.html.twig file looks like this
{% embed 'modal.html.twig' %}
{% block labelledby %}addnewquestion{% endblock %}
{% block modalId %}addnewquestion{% endblock %}
{% block modalHead %}
{{ 'client.modal.head'| trans }}
{% endblock %}
{% block modalBody %}
{{form_start(addAjaxQuestionForm)}}
<div>
{{form_widget(addAjaxQuestionForm.section, {value: section.id})}}
</div>
<div class="form-group">
{{form_label(addAjaxQuestionForm.name, null, {'label_attr': {'class': 'form-label'}}) }}
<span class="help"></span>
<div class="controls">
{{form_widget(addAjaxQuestionForm.name, {'attr':{'class':'form-control'}})}}
</div>
</div>
<div class="form-group">
{{form_label(addAjaxQuestionForm.category, null, {'label_attr': {'class': 'form-label'}}) }}
<span class="help"></span>
<div class="controls">
{{form_widget(addAjaxQuestionForm.category, {'attr':{'width':'100%'}})}}
</div>
</div>
{% endblock %}
{% block modalFooter %}
<button class="btn btn-default" data-dismiss="modal" type="button">{{'client.form.cancel'| trans}}</button>
<input class="btn btn-primary create" type="submit" value="{{'client.form.add.client'| trans}}">
{{form_end(addAjaxQuestionForm)}}
{% endblock %}
{% endembed %}
And finally I have an edit.html.twig that looks like this
<div aria-hidden="true" aria-labelledby="{% block labelledby %}{% endblock %}" class="modal fade" id="{% block modalId %}{% endblock %}" role="dialog" tabindex="-1">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button aria-hidden="true" class="close" data-dismiss="modal" type="button">×</button>
<h4 class="modal-title" id="myModalLabel">{% block modalHead %}{% endblock %}</h4>
</div>
<div class="modal-body">
{% block modalBody %}
{% endblock %}
</div>
<div class="modal-footer">
{% block modalFooter %}
{% endblock %}
</div>
</div>
</div>
</div>
{% include 'AppBundle:Form:ajaxAddQuestionForm.html.twig' %}
Now I get the following error:
Variable "addAjaxQuestionForm" does not exist in src/AppBundle/Resources/views/Form/ajaxAddQuestionForm.html.twig at line 9
Any idea what is wrong with my code?
In your edit.html.twig (assuming your addAjaxQuestionForm variable exists in it), you need to pass it on to the included twig.
{% include 'AppBundle:Form:ajaxAddQuestionForm.html.twig' with {'addAjaxQuestionForm': addAjaxQuestionForm} %}
Try to use
{{ render(controller('AppBundle:Section:ajaxAddQuestionFormAction',{'section':section})) }}
Instead of Include and you must add "section" parameter to ajaxAddQuestionFormAction.
We can help you more than that if you don't publish us all the code that concern the part of your problem.
I hope that helps
You should use render controller method instead of include
{{ render(controller(
'AppBundle:Form:ajaxAddQuestionForm',
{ 'section': section }
)) }}
read more about it here: http://symfony.com/doc/current/book/templating.html#embedding-controllers

Use parent and child blocks in a for-loop, including variables

Is there are way I can create an easily maintainable for loop in Twig that works with Bootstrap's layout?
I'm using bootstrap's row functionality, meaning that each row has a div of class "row". This makes things tricky in twig, because I have no way of entering these header divs.
For example, my main page will have several articles, and extends the skeleton template, as shown below. Is there any way I can use this skeleton base and use it multiple times in a for loop?
I've tried by adding the Article block, but it overrides everything inside. Do I have to create another template for this to work?
<div id="main" class="container-fluid">
{% block article %}
<div class="row">
<div class="col-md-3"></div>
<div id="title" class="col-md-6">
{% block title %}
{% endblock title %}
</div>
<div class="col-md-3"></div>
</div>
<div class="row">
<div class="col-md-1"></div>
<div id="left-nav" class="col-md-2">
{% block left_nav %}
{% endblock left_nav %}
</div>
<div class="col-md-6" id="content">
{% block content %}
{% endblock content %}
</div>
<div id="right-nav" class="col-md-2">
{% block right_nav %}
{% endblock right_nav %}
</div>
<div class="col-md-1"></div>
</div>
{% endblock article %}
</div>
How do I iterate and create multiple "Articles" in this context?
Using parent() isn't helpful because it'll just print the start and end tags, wheras I need them to be placed around the correct sections, otherwise the rows won't work.
In other words, in a for loop context, how can I change the values of variables inside child blocks within a parent block?
Apologies if this is unclear, I found it hard to put into words.
Edit:
I know the existence of for loops in twig, I am just unsure of how to implement a solution to this particular problem.
As a simple example of the skeleton template and its output:
Template
<div class="row">
<div class="title">
{% block title %}{% endblock %}
</div>
<div id="content">
{% block content %}{% endblock %}
</div>
</div>
Output
<div class="row">
<div class="title">
This is the first post.
</div>
<div id="content">
Post 1
</div>
</div>
<div class="row">
<div class="title">
This is the second post.
</div>
<div id="content">
Post 2
</div>
</div>
I found a solution that is fairly maintainable, as it still extends the skeleton template, but is flexible enough to support for loops inside a block.
Skeleton
<div id="main" class="container-fluid">
{% block article %}
<div class="row">
<div class="col-md-3"></div>
<div id="whitespace" class="col-md-6">
{% block title %}
{% endblock title %}
</div>
<div class="col-md-3"></div>
</div>
<div class="row">
<div class="col-md-1"></div>
<div id="left-nav" class="col-md-2">
{% block left_nav %}
{% endblock left_nav %}
</div>
<div class="col-md-6" id="content">
{% block content %}
{% endblock content %}
</div>
<div id="right-nav" class="col-md-2">
{% block right_nav %}
{% endblock right_nav %}
</div>
<div class="col-md-1"></div>
</div>
{% endblock article %}
</div>
Article list
{% extends 'skeleton.php' %}
{% block article %}
{% for post in posts %}
<div class="row">
{# Start title #}
<div class="col-md-3"></div>
<div id="title" class="col-md-6">
{{post.title}}
</div>
<div class="col-md-3"></div>
{# End title #}
</div>
<div class="row">
<div class="col-md-1"></div>
{# Start left-nav #}
<div id="left-nav" class="col-md-2">
{{post.left}}
</div>
{# end left-nav #}
{# Start content #}
<div class="col-md-6" id="content">
{{post.getBody}}
</div>
{# end content #}
{# start right-nav #}
<div id="right-nav" class="col-md-2">
{{post.right}}
</div>
{# end right-nav #}
<div class="col-md-1"></div>
</div>
{% endfor %}
{% endblock article %}
{% foreach article in articles %}
<div class="row">
<div class="title">
{{ article.title }}
</div>
<div id="content">
{{ article.content }}
</div>
</div>
{% endfor %}
Is the template assuming articles is an array containing arrays with keys title and content

Categories