Symfony2 How to create specific collection widget for specific colletion in deep collection form nesting - forms

I have little more complex problem, i have never done more than 1 nested form in an a form, which was fine to just include a custom collection widget template. (Reason: I need to re-code website based on laravel and Spaghetti code, with Spaghetti structure with tons of bugs and buggy patches, what i am fixing for a year now, and i have decided to recreate this app on my loved Symfony).
Let me write the structure:
Questionnaire (short name QN for later use)
- QN -
|_ QN Sections -
|_ QN Parts -
|_ QN Groups -
|_ QN Questions -
|_ some predefined answers
As you can see each QN can have Sections, these sections can have parts, these parts can have groups, and these groups can have questions, these questions have some conditional fields like if question type is "A,B,C" it has another nested collection form for these predefined answers,...
Problem is that for each of these collection form, i need to specify somehow a custom collection wiget template, because each of these collection form has different layout of fields, how they are displayed and handled.
Currently i have created a collection widget template that i include before QN Sections to style QN Sections, but this template is used also for his child collection form, what i need to avoid.
In a perfect world it should work like "prototype_template" => "some path", and then create javascript for each tempalte to add, remove, etc.
Here is an screenshot with some information how it looks now:
In final stage using these separate templates for each collection form, the "form builder" should look like actual web app.
If you need more informations please let me know, i will provide as much informations as i can.
To recap: I need somehow to specify for each nested collection form type to use different collection form widget template.
Thank you

Finnaly I got it.
The main collection template i have used was collection_widget block.
That was bad because it was too general. I hav renamed it to _questionnaire_questionnaireSections_widget, so the 1. level collection were themed. But after day of headake, 1000 combinations of form names i have got how to name the 2. level collection, its block name is "_questionnaire_questionnaireSections_entry_questionnaireParts_widget" what simply stand for "_mainFormTypeName_fieldNameOfFirstCLevelCollection_entry_FieldNameOfSecondLevelCollection_widget"
Than i just needed to place each template file to right place at the right moment.
edit.html.twig
{{ form_start(form) }}
{% form_theme form "::templates/collection/questionnaire/questionnaireSection.html.twig" %}
.........
{{ form_widget(form.questionnaireSections) }}
questionnaireSection.html.twig
{% block _questionnaire_questionnaireSections_widget %}
.............
{% for rows in form %}
{% form_theme form "::templates/collection/questionnaire/questionnairePart.html.twig" %}
questionnairePart.html.twig
{% block _questionnaire_questionnaireSections_entry_questionnaireParts_widget %}
So problem is solved, i have successfully themed nested collections. Thanks to myself and to symfony docs that has 0 words documentation to nested form theming, but they has some information about the "entry " part.

Related

How to add DefaultAdress fields in Customer Sylius Form (symfony3)

I think the title is not very clear, so I will explain better :
I have edited the CustomerRegister form the add a few fields, and I would like to add DefaultAdress fields too (defaultAdress is a linked object to Customer - I have a getDefaultAdresse method in CustomerObject). I would like to add all the fields that are in the DefaultAddress object (street, country, etc.)
I don't know how to do that...
Do I need to modify the CustomerRegistrationTypeExtension to add fields for the address ?
How can I call the fields in my twig file ? Like that : {{ form_row(form.defaultAddress.street) }} ?
I didn't find doc to explain that case.
Thanks for your help !
You should create CustomerRegistrationTypeExtension, just like you described. Inside of this extension, simply do:
use Sylius\Bundle\AddressingBundle\Form\Type\AddressType;
$builder->add('defaultAddress', AddressType::class)
Then override the template and you should be able to render the fields or entire form with:
{{ form_widget(form.defaultAddress) }}
I'd recommend using our standard address form template, by simply including it:
{% include '#SyliusShop/Common/Form/_address.html.twig' with {'form': form.defaultAddress} %}

Drupal 8 form and view in block

I am very new Drupal, In a block I would like to have a form with select box and submit button. Each options in the link is link of content page. That is when the user select an option and click the submit button it will redirect to other node page.
For the above requirement client used Web Form for Drupal 7 and I would like to clone the requirement for Drupal 8. I tried EForm and I am able to create a form but I can not able to show the form in Block Layout and View.
I am not sure the module Eform is suitable for my requirement.
Can you guys please help me what modules do I need to install for the above requirement in Drupal 8.
Okay, I don't know if there are any modules out there which do exactly what you want to, but you can build your own custom solution. In my eyes there are two main possibilities:
create a custom block type with a HTML body field, put your HTML in there and you're done. Advantage: easy to do, Disadvantage: hardcoded
clean way: create a new node type and/or a new category, which you will use for your country nodes. Then you'll create a block programmatically and query for all nodes of that certain country type or for nodes with the "country page"-category, whatever you use to organize those nodes. Then you just create a form out of that data and render it.
Advantage: dynamic, the select list will update itself whenever you add or delete new nodes of that type / category. Disadvantage: takes more effort initially
I personally would recommend using option 2. Option 1 is better for really simple and "stupid" requirements like showing some hardcoded text/image on several places on your site, or if it's something temporary like some campaign teaser, which will be over in 1 week and you'll throw it away after that.
EDIT:
Entity Query: https://api.drupal.org/api/drupal/core!lib!Drupal.php/function/Drupal%3A%3AentityQuery/8
How to build Forms in Drupal 8:
https://www.drupal.org/node/2117411
For display only your block in your templates with preprocess the best way is:
$block = \Drupal\block\Entity\Block::load('my_block_id');
$variables['My_region'] = \Drupal::entityManager()
->getViewBuilder('block')
->view($block);
And in your page.html.twig or node.html.twig or xxx.html.twig use your variable My_region like this :
{% if page.My_region %}
{{ page.My_region }}
{% endif %}
For details check:
https://drupal.stackexchange.com/questions/171686/how-can-i-programmatically-display-a-block

how to display particular fields in form Symfony 2.6

I need display particular fields in form in Symfony 2.6. I use a class Form. I have the folowing fields: name, email, message, send, recet. I need display all of them except recet .I try like this:
{{form_start(form)}}
{{ form_errors(form) }}
{{form_row(form.name)}}
{{form_row(form.email)}}
{{form_row(form.message)}}
{{form_end(form)}}
But, it's displaying all fields in form, it is not what I want. Even if i leave only {{form_start(form)}} and {{form_end(form)}} - its display all fields. Can someone help me wit this problem?
remove form_end, just close form with HTML
</form>
but then you must handle CSRF token generation by adding:
{{ form_widget(form._token) }}
{{ form_widget(form._token) }}
or try setting field you do not want to show using:
{% do form.recet.setRendered %}
but probably best way is not to add this field in the first place, rather than hiding it, by form options or event listeners depending on some criterias
A better solution is to remove the field from the form type. If you only remove it from the view, it may be interpreted as a blank submission for that field and delete existing data.
If you only use the form in one place, then just remove the field from the type. If you use it in multiple places, then you can selectively remove the field in a FormEvents::POST_SET_DATA event listener.

Symfony2 Custom form field for hierarchy in select element

I created a custom form field extending de entity field for display a select with hierarchy of destinations. Table destination is a nested tree based on gedmo Nested Tree behavior. It's works fine but i need to show the hierarchy in select options based on tree level. For example:
Destination1
--Subdestination
--Subdestination
Destination2
--Subdestination
--Subdestination
----Subdestination
I build the tree correctly in custom form field class but i dont know how render properly the options for this select type. I was thinking via form theming override the block {% block choice_widget_options %} but this affect all selects.
How can i do that or there are a best way to do it?
you could try to implement __toString() function on your entity so ti displays proper number of "---" before label
check vendor\symfony\symfony\src\Symfony\Bridge\Twig\Resources\views\Form\form_div_layout.html.twig to see how it workds and override the {% block choice_widget_expanded %} block or whichever type of list you use, you need to add {% form_theme form _self %} in the .twig file where your form is so the twig will search for overriden blocks in the same file

Generate subform in ajax call

I have a form with collection of subforms - student with different studies - relation manyToOne. I have corrent database schema and entities and form builder works well. I don't know how to append new "study" object. I need to get html tags from somewhere in either cases - when there is at least one "study: object (clone him) or there is no such a one.
Let's assume that study object has 2 fields: name and year. If for a student there is such a record (object) it's first input in generated form has name "student[study][0][name]". And is surrounded by . When I click "Add new study" button I want to duplicate this surrounding div and change id's and name's of html form elements respectively. Is there ready library or method to use?
But there may happen there is no study records so far. So I need to get form from server through ajax call. Unfortunately returned form has inputs with names like "study[name]". Is it possible to render this form similar to first case - I mean "student[study][0][name]". But i'd like to avoid manually generate twig template for form - I prefer
{{ form_widget(form) }}
You should be dealing with data-prototype rather than issuing separate AJAX request. The whole concept of adding/removing subform items is described here:
http://symfony.com/doc/current/reference/forms/types/collection.html#adding-and-removing-items
Obviously, you will need to some JS (jQuery is highly recommended) in order to replicate subform fields.
You should note, however, that data-prototype behaves differently when you initially have empty or non-empty collection. At least I have encountered this weird behavior. As far as I remember, in first your when you say {{ form_rest(form) }} additional DIV is appended with data-prototype attribute consisting of form's HTML. In second case actual HTML (not as an attribute) is appended with ID attribute "form_name_$$name$$" where you need to replace $$name$$ with proper index.
Now, you really should take a look - maybe all this has been fixed in some recent versions but I can't be sure...
Hope this helps a bit...