Adding your own action to the SonataAdminBundle dropdown menu

We are using SonataAdminBundle with our Symfony2 application. When editing an object, I want to add my own action to the dropdown menu that is in the upper right corner, but I have no idea how it works.

I know I can add my own routes via configureRoutes(RouteCollection $collection)

and how to add batch actions or add my own actions behind objects in the list view, but how do I add my own link to the action dropdown in edit view?

It is mostly just a link like "Show me this entity in the interface" so it doesn't need a lot of logic.

+3


source to share


3 answers


One way is to override the template used when editing. Now you need to do the following:

  • Create a new directory (if you don't already have one) in app/Resources

    that called SonataAdminBundle

    . Inside, create another one called views

    . This would create a path similar app/Resources/SonataAdminBundle/views

    . This is the main Symfony template. You can read more about this topic here.

  • Now you should copy the original template in the same path as it inside the original package. The template file we are interested in is in sonata-project/admin-bundle/Resources/views/CRUD/base_edit.html.twig

    . This means that you need to create another folder inside views

    (the one we just created in app

    is called CRUD

    . So now we have to follow the next path app/Resources/SonataAdminBundle/views/CRUD

    . Insert the template ( base_edit.html.twig

    ) inside and we can start editing.

Remember that each edit action uses the following template. So it's up to you whether you want to display this link in every edit_action or not. I'll show you one way to limit this to specific actions.

The block that you are going to edit {% block actions %}

, which is responsible for rendering the dropdown. This is how it should look now:



{% block actions %}
    <li>{% include 'SonataAdminBundle:Button:show_button.html.twig' %}</li>
    <li>{% include 'SonataAdminBundle:Button:history_button.html.twig' %}</li>
    <li>{% include 'SonataAdminBundle:Button:acl_button.html.twig' %}</li>
    <li>{% include 'SonataAdminBundle:Button:list_button.html.twig' %}</li>
    <li>{% include 'SonataAdminBundle:Button:create_button.html.twig' %}</li>
{% endblock %}

      

Now all that's left to do is insert the link after the last tag <li>

.

{% if admin.id(object) is not null and app.request.get('_route') == 'my_route' %}
<li>
    <a href="/generate/path/with/your/route">View in Frontend</a>
</li>
{% endif %}

      

admin.id(object)

will return the current id of the item being edited. app.request.get('_route')

will return the route of your edit action. You can remove this if you want your link to appear in all edit actions. Change <a href="/generate/path/with/your/route">View in Frontend</a>

your route name using admin.id(object)

, and you should be good to go.

+4


source


In your admin class, override the following method:

public function getActionButtons($action, $object = null)
{
    $list = parent::getActionButtons($action, $object);

    $list['upload'] = [
        'template' => ':admin:my_upload_button.html.twig',
    ];

    return $list;
}

      

This will add a custom action button on all pages of this admin. You can add any logic here to decide on which pages ( $action

-s) you want to display the button.



You can do what you want in the template, but just to complete my example and show the connection to my custom action:

<li>
    <a class="sonata-action-element" href="{{ admin.generateUrl('upload') }}">
        <i class="fa fa-cloud-upload" aria-hidden="true"></i>
        Upload stuff
    </a>
</li>

      

+2


source


Another way would be to override the method generateObjectUrl()

in the class of the object class.

/**
 * @see \Sonata\AdminBundle\Admin\Admin::generateObjectUrl()
 */
public function generateObjectUrl($name, $object, array $parameters = array(), $absolute = false)
{
    if ('show' == $name) {
        return $this->getRouteGenerator()->generate('your_route_to_public_facing_view', [
            'id' => $this->getUrlsafeIdentifier($object),
        ], $absolute );
    }
    $parameters['id'] = $this->getUrlsafeIdentifier($object);
    return $this->generateUrl($name, $parameters, $absolute);
}

      

What is it. No template junk. And no boilerplate code that will work for all other admins.

To get the link to appear automatically, you need to add something in $showMapper

via configureShowFields()

. (If anyone knows a better way, please tell me.)

Overriding generateObjectUrl()

has another bonus: if you click show

on the button $listMapper

, the URL will be updated there.

Edited to say: since this overrides the route show

, you will no longer be able to use this built-in function. This is ok for me, since I need to view my object with all loading css and js frontend.

0


source







All Articles