how to embed one to many sonata admin child views in ConfigeShowFields - symfony

I have a one to many relationship between account and contacts. I use sonata admin bundle
I want to display all contacts of an account in the view detail of an account ( ConfigureShowFields in AccountAdmin class)
in class AcountAdmin.php i have :
protected function configureShowFields(ShowMapper $showMapper)
{
$showMapper
# .......
->with('Liste des contacts', array('class' => 'col-md-12'))
->add('contacts')
->end()
;
}

I believe you can do this via sonata_type_collection.
->add('contacts', 'sonata_type_collection', array(
'associated_property' => 'email',
'route' => array(
'name' => 'show'
),
'admin_code' => 'app.admin.contacts',
))
The associated_property is the associated property found in the Contacts entity, and the admin_code is the contacts admin.

Related

doctrine : ManyToOne : the field is inserted in the DB with NULL value [duplicate]

I'm searching how to implement a system of choosing languages dynamically using form builder.
so we must have two html array inputs field : name="languages[]" and the second will be name="languges_level[]"
So this system allows the user to set the language which he can speak with his level on it.
The User can add/remove Language dynamically before he submits the Form.
The Questions :
1- Form Level : what will be the field form type? I have to add 2 form fields which will be combined to create my result array which will be stored in the database. So this two field will be not mapped with ORM.
->add('langues', TYPEXXX:class)
->add('langues_level', TYPEXXX:class)
3- Twig Level: should i make some change in the twig as well?
So what will be the best solution in my case?
My first try is :
->add('languages', CollectionType::class, array(
'entry_type' => ChoiceType::class,
'entry_options' => array(
'choices' => array(
'Français' => 'Français',
'English' => 'English',
'Italien' => 'Italien',
'Espanish' => 'Espanish',
),
'label' => ' ',
),
))
->add('language_levels', CollectionType::class, array(
'entry_type' => ChoiceType::class,
'entry_options' => array(
'choices' => array(
'Beginner' => 'Beginner',
'Medium' => 'Medium',
'Good' => 'Good',
),
'label' => ' ',
),
));
but this don't work as I mentioned in the picture .. who had a perfect solution plz ?
I think you need a Collection of Forms.
so we must have two html array inputs field : name="langues[]" and the
second will be name="langes_level[]"
(..)
3- Twig Level: should i make some change in the twig as well?
(..)
4- Javascript Level, i can develop it when the inputs are clean
created in the html.
No, no and no. Describing how your 'array input fields' should be named exactly is not the right mentality if you're using a framework like Symfony. Describe your entity fields, describe your form fields and Symfony will give all form elements a name. Symfony Forms will render and handle the form for you, so there is (very likely) no need to be bothered what the form element names are exactly.
Your entity class:
class LanguageLevel
{
protected $user;
protected $language;
protected $level;
//getters and setters
}
Create a form type:
class UserType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder->add('languages', CollectionType::class, array(
'entry_type' => LanguageLevelType::class,
'allow_add' => true,
));
}
}
And a LanguageLevelType:
class LanguageLevelType extends AbstractType
{
public function buildForm(FormBuilderInterface $builder, array $options)
{
$builder
->add('language', LanguageType::class)
->add('level', ChoiceType::class, array(
'choices' => array(
'Good' => 5,
'Bad' => 1,
),
));
}
}
If the rendered output is not what you want, check the documentation if you can configure the Form Types. Manually changing the twig template, your controller and/or javascripts for a specific case is possible, but I think the 'Collection of Forms' from above will cover your use case.

How to retrieve subject in Sonata configureListFields?

I use Sonata Admin Bundle in my Symfony project and created an ArticleAdmin class for my Article entity.
In the list page, I added some custom actions to quickly publish, unpublish, delete & preview each article.
What I want to do is to hide publish button when an article is already published & vice versa.
To do this, I need to have access to each object in method configureListFields(). I would do something like this:
protected function configureListFields(ListMapper $listMapper)
{
$listMapper->add('title');
// ...
/** #var Article article */
$article = $this->getSubject();
// Actions for all items.
$actions = array(
'delete' => array(),
'preview' => array(
'template' => 'AppBundle:ArticleAdmin:list__action_preview.html.twig',
),
);
// Manage actions depending on article's status.
if ($article->isPublished()) {
$actions['draft']['template'] = 'AppBundle:ArticleAdmin:list__action_draft.html.twig';
} else {
$actions['publish']['template'] = 'AppBundle:ArticleAdmin:list__action_preview.html.twig';
}
$listMapper->add('_actions', null, array('actions' => $actions));
}
But $this->getSubjet() always returns NULL. I also tried $listMapper->getAdmin()->getSubject() and many other getters but always the same result.
What am I doing wrong ?
Thanks for reading & have a good day :)
You can do the check directly in the _action template, as you can access the current subject.
protected function configureListFields(ListMapper $listMapper)
{
$listMapper
->add('title')
->add('_action', 'actions', array(
'actions' => array(
'delete' => array(),
'preview' => array(
'template' => 'AppBundle:ArticleAdmin:list__action_preview.html.twig',
),
'draft' => array(
'template' => 'AppBundle:ArticleAdmin:list__action_draft.html.twig',
),
'publish' => array(
'template' => 'AppBundle:ArticleAdmin:list__action_publish.html.twig',
),
))
;
}
And for example in AppBundle:ArticleAdmin:list__action_draft.html.twig, you can check your condition :
{% if object.isPublished %}
your html code
{% endif %}

symfony sonata admin roles on embedded onetomany entities

I have Symfony 2.3 + Sonata Admin + Sonata User Bundle.
I have created an entity Student, and another entity Contact. An Student have one-to-many relationship with Contact. I have added Contact to Student with sonata_type_collection in my StudentAdmin class. I also have created a group of users Operator and assigned all permissions to Student, but only list and view to Contact.
My problem is that any user of Operator can't add or delete Contact (from Student edit page), but they can edit (and values are saved).
Any suggestions or examples?
Some code:
Roles assigned:
ROLE_SONATA_ADMIN_STUDENT_EDIT
ROLE_SONATA_ADMIN_STUDENT_LIST
ROLE_SONATA_ADMIN_STUDENT_CREATE
ROLE_SONATA_ADMIN_STUDENT_VIEW
ROLE_SONATA_ADMIN_STUDENT_DELETE
ROLE_SONATA_ADMIN_CONTACT_LIST
ROLE_SONATA_ADMIN_CONTACT_VIEW
ROLE_ADMIN: ROLE_USER, ROLE_SONATA_ADMIN
/**
* #ORM\OneToMany(targetEntity="MyBundle\Entity\Contact",
mappedBy="student",
cascade={"persist", "remove"})
**/
private $contact;
->add('contact', 'sonata_type_collection',
array(
'label' => 'Contact',
'by_reference' => false,
),
array(
'edit' => 'inline',
'inline' => 'table',
))
Thanks!
I understood your problem and I don't think Sonata handle this by default.
You have to check the current user roles and either remove contact fields or add readonly or disabled attribute on the contact fields.
Remove Contact Fields
protected function configureFormFields(FormMapper $formMapper)
{
// check if current user has role contact edition
$hasContactRole = $this->getConfigurationPool()->getContainer()->get('security.context')->isGranted('ROLE_SONATA_ADMIN_CONTACT_EDIT'));
if ($hasContactRole) {
$formMapper->add('contact', 'sonata_type_collection',
array(
'label' => 'Contact',
'by_reference' => false,
),
array(
'edit' => 'inline',
'inline' => 'table',
)
);
}
}

Add roles in FOSUserBundle

I feel the same as a forum user who posted this:
I implemented FOSUserBundle, and I want to add to RegisrationFormType roles that are taken from a table. When I had it like this:
->add('roles', 'choice', array('label' => 'Rol', 'required' => true,
'choices' => array( 'ROLE_ADMIN' => 'ADMINISTRADOR','ROLE_SUPERADMIN' => 'SUPERADMINISTRADOR',
'ROLE_USER' => 'USUARIO'), 'multiple' => true))
And it works! But they must leave the BD, I can not put the Entity field because roles should be an array, not an object. How I can generate the array with the roles taken from a table? In FosUSerbundle as you would add roles?
Thanks ....
I write because that user had no answer. I followed [the steps of official documentation] (https://github.com/FriendsOfSymfony/FOSUserBundle/blob/master/Resources/doc/index.md) and adding the above lines in the register of FOSUserBundle works, but I want to work this from the database.
And then I used to create groups this. Two additional tables were created and even now joined a group or role in the list, but not how to show the login to register a new user.
Has anyone solved it?
So you have the roles in a table? You could inject the EntityManager in the form type and use it to fetch the choices.
->add('roles', 'choice', array(
'label' => 'Rol',
'choices' => $this->getRoles(),
'multiple' => true,
'required' => true,
))
Then create a method which gives you the data the way you need.
Something like:
public function getRoles()
{
$roles = array();
$er = $this->em->getRepository('AppBundle:Role');
$results = $er->createQueryBuilder('r')
// conditions here
->getQuery()
->getResult();
// process the array?
foreach ($results as $role) {
$roles[$role->getId()] = $role->getLabel();
}
return $roles;
}

Use sonata_type_collection inside custom type

What I want to do is add sonata_type_collection to my custom formType.
Normal way is add sonata_collection_type to $formMaper inside AdminClass like:
protected function configureFormFields(FormMapper $formMapper)
{
$formMapper->add('elements, 'sonata_type_collection', array(
'some_options' => 'options'
))
}
It work perfect, but i have my custom form type, and when i defined it like:
public function buildForm(FormBuilderInterface $builder, array $options)
{
$formMapper->add('elements, 'sonata_type_collection', array(
'some_options' => 'options'
))
}
It doesn't work (it appear only label of filed). Problem is wrong template, so I tried to set formAdminTemplate
I made it by set template in view
{% form_theme formElement 'SonataDoctrineORMAdminBundle:Form:form_admin_fields.html.twig' %}
Problem is sonata_admin variable inside this 'formTheme'. This variable doesn't exist in my form.
Of course my form type is related to admin class but i don't know how could I I tell symfony about this relation
You need an admin class for your collection child :
$formMapper->add('customizations', 'sonata_type_collection',
array(
'required' => true,
'type_options' => array('delete' => true),
'by_reference' => false,
'mapped' => true
),
array(
'edit' => 'inline',
'inline' => 'table',
'sortable' => 'position',
'targetEntity' => '/path/to/Entity/Customization',
'admin_code' => 'my.service.customization_admin'
)
);
I find solution. Instead using my custom type, I defined form using admin class. I need this form outside admin so it was little difficult.
First of all in my controller i get admin class from service. Inside admin class I override 3 methods which are use to create form
public function getFormBuilder()
public function defineFormBuilder(FormBuilder $formBuilder)
public function buildForm()
then i had to save my entity by sonata admin way. using create method instead handleRequest.

Resources