Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[POC] Add a modal action whose content is loaded via an HTTP call. #164

Merged
merged 7 commits into from
Jan 18, 2025

Conversation

alexandre-castelain
Copy link
Contributor

Hey !

Here is a POC I created to experiment with the bundle.

The idea is to open a modal with content loaded asynchronously. For instance, this could be used to display the details of a product without redirecting to another page. This is a feature I use frequently in my projects.

I left the base.html.twig theme "as is" since I didn’t add any custom JavaScript to it. Depending on the user’s theme, it should be possible to open any kind of modal.

Here’s an example of how I implemented it:

$builder->addRowAction('View detail', ModalActionType::class, [
    'route' => 'app_product_detail',
    'route_params' => function(Product $product) {
        return ['id' => $product->getId()];
    },
])
->addBatchAction('Batch modal', ModalActionType::class, [
    'route' => 'app_product_batch_detail',
])
->addAction('View global detail', ModalActionType::class, [
    'route' => 'app_product_global_detail',
]);

This is the way I use it in my test project. As you can see, you can either use the route/route_params options or the href one, as discussed in another issue.
Unfortunately I didn't manage to get the BatchAction working properly. Ideally, I would like to send the selected rows with the HTTP call.

The controller’s response must return raw HTML, like this:

//src/Controller/ProductController
#[Route('/{id}', name: 'app_product_detail')]
public function detail(Product $product): Response
{
    return $this->render('product/detail.html.twig', [
        'product' => $product,
    ]);
}
{# product/detail.html.twig #}
<div class="modal-dialog">
    <div class="modal-content">
        <div class="modal-header">
            <h5 class="modal-title">Ok, this loads properly !</h5>
            <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Fermer"></button>
        </div>
        <div class="modal-body">
            <p>Here is the result of the AJAX request. The product name is : {{ product.name }}</p>
        </div>
        <div class="modal-footer">
            <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Fermer</button>
        </div>
    </div>
</div>

And this is the result:
image

Using this kind of modal, it's even possible to manage a form in a modal. Thanks to a little bit of JavaScript (e.g., Stimulus 👀 ), you can refresh the form, display errors, submit it, and redirect to user properly afterward.

What do you think about it ?

I’m not a huge fan of having the controller in a subfolder. Since it’s tightly coupled to Bootstrap 5, I’m not quite sure how to handle this in the most appropriate way. Any suggestions?

@Kreyu
Copy link
Owner

Kreyu commented Jan 8, 2025

Thank you for the contribution. I've worked with modal actions, but never implemented them directly in the bundle.

In one of my projects, I've implemented modal action type to use primarily with batch actions. In my case, it was showing a form that sends an email or SMS for selected clients. Excuse non-english, it shows selected clients with and without phone number for validation purposes, since you can select anything in batch:

image

For more details, I copied some code into a gist, it may be useful: https://gist.github.com/Kreyu/f58f05acfcf9f8e99cc2d97ecd5bf1e8

Small disclaimer - the modal controller in the gist is responsible for most modals in the application, not only for data table. That's why it contains a logic that checks whether the modal contents should be fetched from an URL or not (its contents may be already rendered). This shouldn't matter here, I think?

Not sure why your implementation doesn't work with batch controller - I'll have to check it in a demo app and I'll come back to you (maybe this gist will help a bit 😄).

I’m not a huge fan of having the controller in a subfolder. Since it’s tightly coupled to Bootstrap 5, I’m not quite sure how to handle this in the most appropriate way. Any suggestions?

I think grouping the controllers by theme is perfectly fine! Makes it clear that the controller is strictly related with Bootstrap.

However, I suggest changing the default configuration to make the controller disabled by default. Then, developers will be able to opt-in rather than opt-out. This requires a clear note in the documentation.

"bootstrap-modal": {
    "main": "controllers/bootstrap/modal.js",
    "fetch": "eager",
    "enabled": false // instead of true
}

@alexandre-castelain
Copy link
Contributor Author

Thanks for the code, it helped me understand the way batch action should work.

The problem was that the div I use does not contain any href, so it was not possible to update it properly. I updated a little the batch.js controller to make the 'href' configurable.

I don't like the fact that the URL must be absolute, I would have preferred relative ones. What do you think ?

@Kreyu
Copy link
Owner

Kreyu commented Jan 9, 2025

I don't like the fact that the URL must be absolute, I would have preferred relative ones. What do you think ?

Sure, I think we can support both:

href = new URL(identifierHolder.dataset[hrefHolder], window.location.origin);

obraz

assets/controllers/batch.js Outdated Show resolved Hide resolved
Copy link
Owner

@Kreyu Kreyu left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I think it should work fine in the current state. That will be the last feature for the 0.26 release. Could you please resolve the conflicts that appeared after merging the dropdown action type and some other fixes? I'll add documentation for the action type in the separate PR. Great job, thank you! 😁

src/Resources/views/themes/bootstrap_5.html.twig Outdated Show resolved Hide resolved
src/Action/Type/ModalActionType.php Outdated Show resolved Hide resolved
@Kreyu Kreyu merged commit f5cef5a into Kreyu:main Jan 18, 2025
10 checks passed
@Kreyu
Copy link
Owner

Kreyu commented Jan 18, 2025

Thank you @alexandre-castelain. I'll add docs in the separate commit.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants