I've two entities: A_ and B_, where B_ is a collection of the A_.
Now in EA edit view B_ collection displays as embedded object:
class A_CrudController extends AbstractCrudController {
public function configureFields(string $pageName): iterable {
...
yield CollectionField::new('b_', 'B_ Collection')
->useEntryCrudForm(B_CrudController::class)
->setEntryIsComplex();
}
}
Everything works fine but I'd like to have a table view this collection where each row is element of the collection.
How to do it?
I try to use method in Symfony EasyAdmin 3 display relation table in parent details page
but it doesn't work for me.
Thanks
Related
I'm learning Symfony and EasyAdmin, my next task on the list is to add a button which will print (generate PDF) selected rows from the table. I've checked in the EasyAdmin docs if there maybe is a tutorial or more info, but without luck. https://symfony.com/bundles/EasyAdminBundle/current/crud.html
How I should approach it? Is there a method I should use or a bundle?
I've found this thread:
PDF document creation EasyAdmin symfony 5 But no one replied. There is not much info regarding this matter.
Symfony 5.4, EasyAdmin 4
I think that you should create a customs actions for this.
Let say that you have setup a ProductCrudController class. In that class, you will have to override this :
public function configureActions(Actions $actions): Actions
{
$viewProductInPDFFormat = Action::new('viewPDF', 'View in PDF', 'fa fa-file-pdf-o')
->linkToRoute('name_of_route_that_generate_pdf_on_one_product',
function (Product $product): array {
return [
'id' => $product->getId(),
];
});
return $actions
//will add the action in the page index view
->add(Crud::PAGE_INDEX, $viewProductInPDFFormat)
//will add the action in the page detail view
->add(Crud::PAGE_DETAIL, $viewProductInPDFFormat)
;
}
Is there any way to show/hide actions based on the underlying entity? For example, I need to show the delete action of a Category entity if and only if it doesn't have any children post.
I tried to remove that from configureActions method in my CRUD controller, but I haven't access to the AdminContext object when that method is being called.
How can I do that?
After tracing in EasyAdmin's code base I found this solution:
Consider I have a Category entity with a OneToMany relation to posts. I need to show delete action of each category if the category doesn't have any post.
public function configureActions(Actions $actions): Actions
{
$action = parent::configureActions($actions)->getAsDto(Crud::PAGE_INDEX)->getAction(Crud::PAGE_INDEX, Action::DELETE);
if (!\is_null($action)) {
$action->setDisplayCallable(function (Category $category) {
return $category->getPosts()->count() === 0;
});
}
return $actions;
}
Looking for a straightforward way to add constraints dynamically to all of my form fields. So far I've hit upon the idea of using a form type extension, which kind of works: I can modify the form view and then manually check the view on form submission.
However, is there a smarter way to add real Symfony-based constraints in real-time?
(Note that the constraints need to be added to the form in real-time as the form loads based on user configuration in the database.. Predefined form groups and the like won't work.)
I would suggest to use form events.
Use the PRE_SUBMIT event to edit the form before validation.
Recreate your fields with $event->getForm()->add(...) adding your constraints.
Of course you can automatically add the listener to all form using a FormExtension which adds the listener.
EDIT : Some examples from Alsatian67/FormBundle
Your extension should looks like :
class ExtensibleExtension extends AbstractTypeExtension
{
private $extensibleSubscriber;
public function __construct($extensibleSubscriber) {
$this->extensibleSubscriber = $extensibleSubscriber;
}
public function buildForm(FormBuilderInterface $builder, array $options)
{
// Only apply on base form
if($builder->getForm()->isRoot())
{
$builder->addEventSubscriber($this->extensibleSubscriber);
}
}
public function getExtendedType()
{
return FormType::class;
}
}
And your EventListener / EventSubscriber should iterate on all the children :
foreach($event->getForm()->all() as $child){
$childName = $child->getName();
$type = get_class($child->getConfig()->getType()->getInnerType());
$options = $child->getConfig()->getOptions();
$options['constraints'] = array(/* ... */);
$form->add($childName,$type,$options);
}
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')) }}