3

I don't like the "edit"-button at the end of each entity on the INDEX-Page (EasyAdmin 3 / symfony 5) and I would like to have the table-row clickable and it shall send me directly to the EDIT-page.

I guess the solution must be using Javascript, so I started:

PHP-file

class PersonCrudController extends AbstractCrudController {
   [...]
   
    public function configureFields(string $pageName): iterable {
        [...]
        yield TextField::new('fullName',  'Name')->onlyOnIndex()->setCssClass('js-row-action');
        [...]
    }

   [...]
}

javascript-file

// call functions once page is loaded
document.addEventListener("DOMContentLoaded", function() {
    makeTableRowClickable();
});

function makeTableRowClickable() {
    let elements = document.getElementsByClassName('js-row-action');

    for (let i = 0; i < elements.length; i++) {
        let td = elements[i];
        let tr = td.parentNode;

        tr.addEventListener("click", function (e) {
            alert('click the row, Jack!');
        });
    }
}

open questions

  1. How do I generate the URL of the EDIT-page?
  2. How can I set a data attribute with the URL into any (hidden) field so that I can use it in the javascript?

Any ideas? Many thanks!

Tim K.
  • 335
  • 4
  • 23

5 Answers5

7

Here is my solution (you have to update the twig-template)

index.html.twig (my overriding file)

identify the URL for the edit-page and add the link as href-attribute into the TR-tag

{#
    EXAMPLES:
    templates/bundles/EasyAdminBundle/layout.html.twig      ===> extends '@!EasyAdmin/layout.html.twig'
    templates/bundles/EasyAdminBundle/crud/index.html.twig  ===> extends '@!EasyAdmin/crud/index.html.twig'
#}

{# DO THIS: the '!' symbol tells Symfony to extend from the original template #}
{% extends '@!EasyAdmin/crud/index.html.twig' %}


{% block table_body %}

    {% for entity in entities %}
        {% if not entity.isAccessible %}
            {% set some_results_are_hidden = true %}
        {% else %}

            {# generation of the EDIT-link #}
            {% set editUrl = ea_url()
                    .setController(ea.crud.controllerFqcn)
                    .setAction('edit')
                    .setEntityId(entity.primaryKeyValue) %}


            {# add href-attribute and insert the URL #}
            <tr data-id="{{ entity.primaryKeyValueAsString }}" href="{{ editUrl }}">

[...]

{% endblock table_body %}

javasript-file

identify the href-attribute and send user to url

// call functions once page is loaded
document.addEventListener("DOMContentLoaded", function() {
    makeTableRowClickable();
});

function makeTableRowClickable() {
    let elements = document.getElementsByClassName('js-row-action');

    for (let i = 0; i < elements.length; i++) {
        let td  = elements[i];
        let tr  = td.parentNode;
        let url = tr.getAttribute('href');

        tr.addEventListener("click", function (e) {
            location.href = url;
        });
    }
}

crud-controller (php)

add a css-class that can be catched by javascript

class PersonCrudController extends AbstractCrudController {
   [...]
   
    public function configureFields(string $pageName): iterable {
        [...]
        yield TextField::new('fullName',  'Name')->onlyOnIndex()->setCssClass('js-row-action');
        [...]
    }

   [...]
}

dashboard-controller (php)

link the javascript-file to the dashboard-controller to have it as default everywhere

class DashboardController extends AbstractDashboardController
{
    [...]
    public function configureAssets(): Assets {
        $assets = parent::configureAssets();
        $assets->addJsFile('js/row_clickable.js');

        return $assets;
    }
    [...]
}

Have fun!

Tim K.
  • 335
  • 4
  • 23
  • Note that now you have to add `.generateUrl()` or it won't work (you'll have the same URL for each entity). Ex: `{% set editUrl = ea_url().setController(ea.crud.controllerFqcn).setAction('edit').setEntityId(entity.primaryKeyValue).gemerateUrl() %}` – mxlhz Apr 14 '22 at 15:18
  • @mxlhz There is a typo in your code. Here is the corrected code for everyone to copy: `{% set editUrl = ea_url().setController(ea.crud.controllerFqcn).setAction('edit').setEntityId(entity.primaryKeyValue).generateUrl() %}` – Quatsch May 03 '22 at 21:22
  • *caught ..................... – Quatsch May 05 '22 at 10:27
  • If you still want to use the inline easyadmin checkboxes while having a clickable row, you can check for it in the event before redirecting. `tr.addEventListener("click", function (e) { if(e.target.getAttribute('type') !== 'checkbox') { location.href = url; } });` – HoppyB May 27 '22 at 20:33
3

Work for me. Symfony 6.1, EasyAdminBundle 4

In crud-controller (PHP)


    public function configureFields(string $pageName): iterable
    {
    //....
    yield IdField::new('id')->onlyOnIndex()        
    ->setTemplatePath('admin/field/linkedit.html.twig');
    yield TextField::new('anyfield')->setLabel("Title")
    ->setTemplatePath('admin/field/linkedit.html.twig');
    //....
    }

Template (TWIG)


    {# admin/field/linkedit.html.twig #}
    {% set editUrl = ea_url()
                        .setController(ea.crud.controllerFqcn)
                        .setAction('edit')
                        .setEntityId(entity.primaryKeyValue) %}
    <a href="{{ editUrl }}" id="Edit_{{ entity.primaryKeyValueAsString }}">{{ field.value }}</a>

"editUrl" variable used from this answer https://stackoverflow.com/a/65017290/19516399

Nikita
  • 31
  • 2
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Jul 11 '22 at 21:08
1

I found an alternative solution that converts the text in a link, and javascript find and takes yo to the edit URL.

public function configureFields(string $pageName): iterable
{
    return [
        TextField::new('firstName')->setCssClass('js-row-action'),

...

public function configureAssets(Assets $assets): Assets
{
    return $assets->addJsFile('js/admin.js');
}

....

$('.js-row-action').each(function () {
    $(this).find('span').html('<a href="#">' + $(this).find('span').text() + 
'</a>');
});

$('.js-row-action').click(function () {
    window.location.href =  
    (this).siblings('td.actions').find('a').attr('href');
});
0

I improved the code grouping all in one jquery instruction:

$('.js-row-action').each(function () {
    $(this).find('span').html('<a href="' + 
$(this).siblings('td.actions').find('a').attr('href') + ' ">' + 
$(this).find('span').text() + '</a>');
});
0

pure javascript version

for (let [key, element] of Object.entries(document.getElementsByClassName('edit-entity'))) {        
    element.innerHTML = '<a href="'+element.parentElement.querySelector('td.actions a').getAttribute('href')+'">'+element.innerHTML+'</a>';
}

CrudController configureFields

yield Field::new('column')->setCssClass('edit-entity');