I have a view that shows the attributes of my parent entity. This Entity will have other child entities. I want the create form for those childs to be placed in my show.html.twig of the parent.
How do I place the create form of those childs in my parents view? How do I combine two controllers of two different entities?
You can create forms for any entity in any controller. Since you didn't post any code it's hard to guess how your controller looks like, but here an example that might help:
public function showMainEntityAction(MainEntity $mainEntity){
...
$childEntity = new ChildEntity();
$childEntity->setMainEntity($mainEntity);
$childEntityForm = $this->createForm(new ChildEntityType(), $childEntity);
...
return $this->render('...show.twig.html', array(
'entity' => $mainEntity,
'childEntityForm' => $childEntityForm
);
}
Of course you have to define a form type for the child entities and add form_widget(childEntityForm) to your template.
Related
Is possible to get some list of fields in FormEvents::PRE_SET_DATA?
I need edit entity which I put to Form by Event. Entity contains PersistCollection which I need transform to ArrayObject.
I would like created on automatic for many entities. I need list of fields (names) for data mapping.
My idea:
$fields = $event->getFormFields();
foreach ($fields as $field) {
dump($field); --> return 'name'
}
It's not completely clear what you're trying to achieve, but yes, you can get all child forms from parent form easily:
You can either use:
foreach ($event->getForm()->all() as $childForm) {
// ...
}
or, since Symfony Form implements IteratorAggregate interface:
foreach ($event->getForm() as $childForm) {
}
Is it bad practice to get data from db in twig function or I should pass it to view in controller?
My function is some kind of interface widget that is used on all pages of site admin section. Then on data change I will have to make changes in all actions. But when I get data directly in extension class our teamlead tells that it's bad MVC.
It would be best if you pass it to a view from a controller.
Your team leader is right. What you can do is create an action specific to render that widget. I.e create a custom widget, let's say you want to show the number of current active users:
class WidgetController extends Controller
{
public function usersCountWidgetAction()
{
return $this->render('widget/usersCount.html.twig', array(
"usersCount" => $this->getUsersCount();
));
}
public function getUsersCount()
{
// call the manager and get the result
}
}
Now in all your other twigs you can use
{{ render(controller('AppBundle:Widget:usersCountWidget')) }}
I have 2 forms. One is the main form with fields and a collection and inside this fields the other form. On each form (the parent and the child) I add a PRE_SUBMIT subscriber. Now, my problem is, I want to load a method specific to the parent form after execution of the PRE_SUBMIT on the child event.
Actually, following the documentation, in spite I give priority, I have always this order :
parent::PRE_SUBMIT -> child::PRE_SUBMIT
and by the way I want :
parent::PRE_SUBMIT -> child::PRE_SUBMIT -> parent::PRE_SUBMIT(other)
Do you have an idea if it's possible to do that and in what way ?
Remove the event PRE_SUBMIT on your children (only add it for the parent), and inside your event handler do the specific code for your children.
E.g.
public function yourPresubmitMethod(FormEvent $event)
{
$form = $event->getForm();
// Code before
// Code for each child
foreach ($form as $child)
{
$child->theChildPreSubmitMethod();
}
// Code after
}
In my project I have an abstract entity, let's call it Parent, and two child entities: ChildA and ChildB that extend Parent class. I'm using doctrine and a single table strategy, has ChildA and ChildB are similiar. This part is working ok, now my problem is with the form.
I want to have a single form that can be used to create an entity of one of those classes (ChildA or ChildB), so I want to have a first field in the form to select which kind of entity the user wants to create, and show the fields for that class (has there are only one different field, I'm using javascript to show/hide the field according to the selected class)
To accomplish this I have created a form with all the fields of both ChildA and ChildB plus the field to select the type, and my idea was in controller check the type, and then create a specific form associated with ChildA or ChildB according to the selected type, and bind it with the valus received from the main form, but the problem here is how to display the errors in this form
Anyone have a good solution for this problem?
I think you make it very difficult this way.
For this problem i would create 2 forms (FormChildA, FormChildB) with the associated fields accordingly.
Because you are using javascript anyway, just render the page with a choice and get the form with ajax:
<div id="select-type">
<button value="child_a" type="button">Select ChildA</button>
<button value="child_b" type="button">Select ChildB</button>
</div>
<div id="form-container"></div>
<script>
$('#select-type button').on('click', function(event) {
event.preventDefault();
$.get('path/to/get_ajax_form', {type: $(this).val()}, function(data) {
$('#form-container').html(data);
});
});
</script>
Create a Controller method to retrieve the form:
public function getAjaxFormAction()
{
$type = $this->get('request')->query->get('type');
switch( $type ) {
case 'child_a':
$form = $this->createForm(new FormChildA, new ChildA);
break;
case 'child_b':
$form = $this->createForm(new FormChildB, new ChildB);
break;
}
return $this->render('AcmeBundle:Forms:_type_form.html.twig', array(
'form' => $form->createView(),
'type' => $type,
));
}
Add to each form a hidden field with the form type value,
this way you can validate these forms in one method (same way as you retrieve them).
This makes it easier to modify and validate each form separately!
This is a follow up question to Drupal Views exposed filter of Author name. The following question was answered and works. I can filter a view by user name. The user name is entered is entered by typing in a box and the box then auto completes. Rather then doing this I would like the list of users as a drop down. I only need one user to be selected. Do you know if this is possible?
You'll need a custom module for that.
I've done this for Drupal 7 this way: create a module, say, views_more_filters, so you have a views_more_filters.info file like this:
name = Views More Filters
description = Additional filters for Views.
core = 7.x
files[] = views_more_filters_handler_filter_author_select.inc
files[] = views_more_filters.views.inc
(file views_more_filters_handler_filter_author_select.inc will contain our filter handler).
A basic views_more_filters.module file:
<?php
/**
* Implements of hook_views_api().
*/
function views_more_filters_views_api() {
return array('api' => 3);
}
Then define your filter in views_more_filters.views.inc:
<?php
/**
* Implements of hook_views_data().
*/
function views_more_filters_views_data() {
return array(
'node' => array(
'author_select' => array(
'group' => t('Content'),
'title' => t('Author UID (select list)'),
'help' => t('Filter by author, choosing from dropdown list.'),
'filter' => array('handler' => 'views_more_filters_handler_filter_author_select'),
'real field' => 'uid',
)
)
);
}
Note that we set author_select as a machine name of the filter, defined filter handler ('handler' => 'views_more_filters_handler_filter_author_select') and a field we will filter by ('real field' => 'uid').
Now we need to implement our filter handler. As our filter functions just like default views_handler_filter_in_operator, we simply extend its class in views_more_filters_handler_filter_author_select.inc file:
<?php
/**
* My custom filter handler
*/
class views_more_filters_handler_filter_author_select extends views_handler_filter_in_operator {
/**
* Override parent get_value_options() function.
*
* #return
* Return the stored values in $this->value_options if someone expects it.
*/
function get_value_options() {
$users_list = entity_load('user');
foreach ($users_list as $user) {
$users[$user->uid] = $user->name;
}
// We don't need Guest user here, so remove it.
unset($users[0]);
// Sort by username.
natsort($users);
$this->value_options = $users;
return $users;
}
}
We haven't had to do much here: just populate options array with a list of our users, the rest is handled by parent class.
For further info see:
Views API
Where can I learn about how to create a custom exposed filter for Views 3 and D7? on Drupal Answers
Demystifying Views API - A developer's guide to integrating with Views
Sophisticated Views filters, part2 - writing custom filter handler (in Russian, link to Google translator)
Tutorial: Creating Custom Filters in Views
Yes, this is possible. Its not particularly tough to do this... but its slightly tedious. You need to create two views
The first view is a list of users on your system (a View of type Users). This user list is displayed as a dropdown instead of a list (using jump menu view style). Clicking on any user within this dropdown will call the second view with the uid (user id) of the selected user as the argument in the URL. This view is a block.
The second view is a simple Node listing. It is a page view at a particular URL. It takes 1 argument which is the uid (user id) of the user.
Detailed Steps
Download the Ctools module
http://drupal.org/project/ctools
Enable the Chaos Tools Module. This
module provides a Views Style Plugin
called "Jump Menu"
Create a new view of type Users and NOT type Node which you usually
create. In the fields add User:
Name and User: uid. For the
settings of User: uid, make sure
you click on Rewrite the output of
the field. The rewritten output of
the field should be
my_node_list/[uid]. Make sure you
select the exclude from display checkbox.
In the settings for Style in the view, select the Jump Menu style. Click on the settings for the style. Make sure the Path dropdown has User: uid choosen
Add a block display to the view. Name the block User Drop Down
Save the view
Add the block User Drop Down to any region in your theme e.g. Content Top (usually the best) or left sidebar. Make sure the block is only visible at the urls my_node_list/* and my_node_list by setting the block visibility settings
Now create another view of type Node. Add an argument field User: uid. Add the fields you are interested in e.g. Node: title, User: Name etc.
Add a page display. Let the page be at the url my_node_list
Save the view. Test the dropdown with its list of users on the system at http://yoursitename/my_node_list
http://drupal.org/project/better_exposed_filters
Check this one
I think you just have to choose "Taxonomy:term The taxonomy term ID" instead of "name".
Found a simple solution here. http://bryanbraun.com/2013/08/06/drupal-tutorials-exposed-filters-with-views