javascript – Set cookie once modal opens on page scroll

$(document).ready(function () {
    const element = document.querySelector('.modalElement');
    if (element) {
        window.addEventListener("scroll", function() {
            if (is_in_viewport(element)) {
                trigger_modal(element);
            }
        });
    }

    /**
     * Trigger modal
     *
     * @param element
     */
    function trigger_modal(element) {
        // Check if correct modal_target gets pulled & user is logged in
        const modal_target = element.getAttribute('data-target');
        const user_logged_in = document.body.classList.contains('logged-in');
        // If user logged in, show modal unconditionally
        if (user_logged_in) {
            $(modal_target).modal('toggle');
        } else {
            // This grabs the correct stored cookie.
            let stored_cookie = get_cookie('acceptedPardot' + modal_target + 'Cookie');
            // If the cookie doesn't exist, set the cookie and allow for opening the modal
            if (!stored_cookie) {
                set_cookie('acceptedPardot' + modal_target + 'Cookie', 'true', 30);
                $(modal_target).modal('toggle');
            }
        }
    }

    /**
     * Set cookie
     *
     * @param name
     * @param value
     * @param days_active
     * @return {string}
     */
    function set_cookie(name, value, days_active) {
        let cookie = name + "=" + encodeURIComponent(value);
        if (typeof days_active === "number") {
            cookie += "; max-age=" + (days_active * 24 * 60 * 60) + "; path=/";
            document.cookie = cookie;
        }
    }

    /**
     * Get cookie
     *
     * @param name
     * @return {string|null}
     */
    function get_cookie(name) {
        const cookie_array = document.cookie.split(";");
        for (let i = 0; i < cookie_array.length; i++) {
            const cookie_pair = cookie_array(i).split("=");
            if (name === cookie_pair(0).trim()) {
                return decodeURIComponent(cookie_pair(1));
            }
        }

        return null;
    }

    /**
     * Check if element is in viewport
     *
     * @param element
     * @return {boolean}
     */
    function is_in_viewport(element) {
        const rect = element.getBoundingClientRect();
        return (
            rect.top >= 0 &&
            rect.left >= 0 &&
            rect.bottom <= (window.innerHeight || document.documentElement.clientHeight) &&
            rect.right <= (window.innerWidth || document.documentElement.clientWidth)
        );
    }
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

<div class="modalElement" data-toggle="modal" data-target="#modal-<?= $id ?>"></div>
<div class="modal fade" id="modal-<?= $id ?>" tabindex="-1" role="dialog" aria-hidden="true">
    <div class="modal-dialog modal-dialog-centered">
        <div class="modal-content">
            <div class="modal-header">
                <h5 class="modal-title" id="exampleModalLabel">Pardot Form</h5>
                <button type="button" class="close" data-dismiss="modal" aria-label="Close">
                    <span aria-hidden="true">&#10005;</span>
                </button>
            </div>
            <div class="modal-body">
                <form>
                    <div class="form-group">
                        <label for="formGroupExampleInput">Example label</label>
                        <input type="text" class="form-control" id="formGroupExampleInput" placeholder="Example input placeholder">
                    </div>
                    <div class="form-group">
                        <label for="formGroupExampleInput2">Another label</label>
                        <input type="text" class="form-control" id="formGroupExampleInput2" placeholder="Another input placeholder">
                    </div>
                </form>
            </div>
            <div class="modal-footer">
                <button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
            </div>
        </div>
    </div>
</div>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusmod tempor incididunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation ullamco laboris nisi ut aliquip ex ea commodo consequat. Duis aute irure dolor in reprehenderit in voluptate velit esse cillum dolore eu fugiat nulla pariatur. Excepteur sint occaecat cupidatat non proident, sunt in culpa qui officia deserunt mollit anim id est laborum.</p>

website design – Inline vs Modal Dialog Editing for complex widgets

I am building an application where user’s can create very complex widgets using a browser. The two main approaches I can think of to allow for this is inline editing and modal dialog boxes.

Unlike a simple text field, these widgets will probably have several tabs of information that they need to configure. One of the tabs will have to be a preview of the widget, and the others will be setting various properties and providing data to the widget.

In addition to all of these complex options, users can move the widgets around too, which means just about everything on the screen is interactable in some way if the widgets allow inline edits.

Popups have the advantage of letting the user deal with 1 widget at time, without thinking about the other ones, but I also worry that maybe they would feel disconnected from the other widgets on the page once they hop back. This does make the previewing of the widgets simpler though… and the page itself will resemble the actual product without all of the editing tools cluttering things up on the page.

Popups also make it easier to make a bunch of changes at once, and then bail out and not commit them. Inline edits could do this too, but then you’d have to present the user with dirty tracking UI.

The last consideration I have is that these widgets have a variety of types, and rather than provide a massive menu with 30 options, I wanted to allow users to refine the type of a widget while it was on the page. So for example, they put down a Media widget and can select from Image, Video, Audio, etc., and then they would allowed to do the inline editing for that type of widget. However this bares the complication that they can bail out of selecting the widget type while it’s still added to the page… something the Modal Dialog would have prevented. I could either not commit that widget to the server, but it may be confusing since they did at it to the page… but untyped widgets would invalidate the data model, which also causes problems.

I am leaning toward dialog boxes actually, but I am curious what the best approach is. I am not a UI designer – just a coder.

Widgets 1

Widgets 2

Modal logic and topology

This Wikipedia article mentions that modal logic is used somehow in Topology. How is modal logic used in Topology? It would be nice to have a result which modal logic helps to proove

forms – Delete confirmation for items within a modal

I have a modal that contains a table of items. Each item is in a row and a user should be able to edit/delete each item.

When deleting an item, there needs to be a confirmation dialog asking the user to confirm the deletion.

The problem with that is a dialog box will be sitting on top of the modal – so it’s essentially a modal on top of a modal.

Is it ok to just display the dialog without the modal behind it?

Please note that time is limited for this issue, so we couldn’t spend a lot of time on a more complex, albeit better, solution.

Django CreateView – Method Not Allowed ao tentar cadastrar carregando form com Bootstrap Modal

Ao tentar submeter um formulário para inserir no banco de dados estou recebendo, no console do navegador, a mensagem de erro Failed to load resource: the server responded with a status of 405 () quando carrego meu template em um Modal Bootstrap na minha ListView.

Quando eu abro o mesmo template “normalmente”, ou seja, sem ser em um Modal, a inserção acontece sem nenhum problema.

Segue, abaixo, os códigos envolvidos no problema.

**view.py**
class UsoVeiculoCreate(CreateView):
    model = UsoVeiculo
    form_class = UsoViaturaForm
    template_name = 'frotaapp/uso-veiculo.html'

    def get(self, request, *args, **kwargs):
        form = self.form_class(initial = self.initial)
        return render(request, self.template_name, {'form':form})

    def post(self, request, *args, **kwargs):
        form = self.form_class(request.POST)

        if form.is_valid():
            model = form.save(commit=False)
            model.condutor_uso = Condutor.objects.get(servidor_condutor=request.user)
            model.save()
            return HttpResponseRedirect(reverse('viatura:uso-veiculo-listar'))            
        else:
            return render(request, self.template_name, {'form':form})

class UsoVeiculoListar(ListView):
    model = UsoVeiculo
    template_name = 'frotaapp/listar-uso-veiculo.html'

    def get_queryset(self):
        return UsoVeiculo.objects.all().order_by("-data_saida_uso")

Código abaixo é do template para inserção do Modelo

{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block rel-adicionais %}
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.7.14/css/bootstrap-datetimepicker.min.css">
{% endblock %}

{% block content %}
  <div class='container'>
      <h3><b><p>Cadastrar Uso de Veículo</b></p></h3>
      {% crispy form %}
  </div>
{% endblock %}

{% block extra-script %}
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.1/moment.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.7.14/js/bootstrap-datetimepicker.min.js"></script>

    <script type="text/javascript">
        $(document).ready(function() {
            $('#id_data_saida_uso').datetimepicker({
                format: 'DD/MM/YYYY HH:mm',
            }).attr("autocomplete", "on");
        });
    </script>

{% endblock %}

Agora o template da minha ListView, onde está o Modal que deve carregar o template acima

{% extends 'base.html' %}

{% load crispy_forms_tags %}

{% block title %}
    <title>Uso dos Veículos</title>
{% endblock %}

{% block rel-adicionais %}
    <link rel="stylesheet" type="text/css" href="https://cdn.datatables.net/v/bs4/dt-1.10.25/datatables.min.css"/>
    <link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.7.14/css/bootstrap-datetimepicker.min.css">
{% endblock %}

{% block content %}
    <h3><b><p class='container'>Usos dos Veículos</b></p></h3>

    <div class='container'>
        <hr/>
        <p class="text-right">

            <a class='open-novo'
                href="{% url 'viatura:uso-veiculo-novo' %}"
                data-popup-url="{% url 'viatura:uso-veiculo-novo' %}"
                title='Registrar Novo Uso'
                >Novo
            </a>

        </p>
        <table id='notificacoes_controle_urbano' class='table table-bordered table-hover'>
            <thead>
                <tr>
                    <th>Data Saída</th>
                    <th>Data Retorno</th>
                    <th>Viatura</th>
                    <th>Condutor</th>
                    <th>KM Início</th>
                    <th>KM Final</th>
                    <th>Ações</th>
                </tr>
            </thead>
            <tbody>
                {% for model in object_list %}
                <tr>
                    <td>{{ model.data_saida_uso }}</td>
                    <td>{{ model.data_retorno_uso }}</td>
                    <td>{{ model.veiculo_uso }}</td>
                    <td>{{ model.condutor_uso }}</td>
                    <td>{{ model.km_inicio_uso }}</td>
                    <td>{{ model.km_fim_uso }}</td>
                    <td>
                        <a href="{% url 'viatura:encerrar-uso' model.pk %}">
                            <button class="btn btn-danger btn-sm" title='Encerrar Uso'>E</button>
                        </a>
                    </td>
                </tr>
                {% endfor %}
            </tbody>
        </table>
    </div>


    <!-- The Modal -->
    <div id="popup" class="modal fade" role="dialog">
      <div class="modal-dialog modal-lg">
        <div class="modal-content">
          <div class="modal-body"></div>
          <div class="modal-footer">
            <button type="button" class="btn btn-info" data-dismiss="modal">Close
            </button>
          </div>
        </div>
      </div>
    </div>
{% endblock %}


{% block extra-script %}
    <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.mask/1.14.15/jquery.mask.min.js"></script>
    <script type="text/javascript" src="https://cdn.datatables.net/v/bs4/dt-1.10.25/datatables.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/moment.js/2.15.1/moment.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-datetimepicker/4.7.14/js/bootstrap-datetimepicker.min.js"></script>

    <script type="text/javascript">
        $(document).ready(function() {
            $('#notificacoes_controle_urbano').DataTable({
                responsive: true,
                "aaSorting": (),
                "pageLength": 50,                
            });
        });

        $(document).on('click', '.open-novo', function(e) {
           e.preventDefault();
           var $popup = $("#popup");
           var popup_url = $(this).data('popup-url');
           $(".modal-body", $popup).load(popup_url, function() {
               $popup.modal("show");
           });
        });
    </script>
{% endblock %}

Desde já agradeço a atenção.

sharepoint online – Edit/Update List Form Item Through a Modal

I am using Dialog popup to create a new list item which uses a people picker to automatically fill in the user field. The way this form works is it gets updated on a day-by-day basis. With the New form button, obviously when you want to update the previous item, it will not do that, it will just open up a new form. With the edit form, I need to add the people picker script, but it still doesn’t do what I want it to. Is there a way I can create a conditional script or something that when the user clicks on the update form button, their specific list item for the week will pop up by searching for their name?

Right now, both of these open up a blank form on click:

<a href="#" class="button" onclick="openDialog('/Lists/MorningReport/NewForm.aspx');">Create New Week Report</a>
<a href="#" class="button" onclick="openDialog('/Lists/MorningReport/EditForm.aspx');">Update Current Week Report</a>

design – ASP.NET Core – Using Partial Views inside a Modal window for my Add/Edit/View Details screens?

I’ve been developing .NET projects for the past 3 years, and on my recent web .NET projects, I’ve been using Partial Views for all the screens that contain Forms for Add/Update/Delete or other information (e.g. User Info).

Here’s a sample (not the exact code) of how I designed it.

For example on editing a user:

HTML - (A table that contains information about users)

<table style="width:100%">
  <tr>
    <th>ID</th>
    <th>Name</th> 
    <th>Edit</th>
  </tr>
   <tr>
   <td>94</td>
    <td>Jackson</td>
    <td><button type="button" onclick="LoadHtmlContent('94')"> Edit </button></td>
  </tr>
</table>

Javascript (Function that is executed when the user clicks the Edit button on the table)

function LoadHtmlContent(id)
{
   var id = id; // Get the id from a table row 
   var url = $("#EditUrl").val(); //Get the URL from a hidden input
   $.ajax({
   url: url,
   type: "GET"
   data: data, //optional
   success: function(response){
     if(response.success=true){
       $("#modal").html(response.content);
       $("#modal").show();
    }
     else{
       alert(response.message)
    }
   }
  )};
}

Controller:

public ActionResult LoadEditableScreen(int id)
{
   //Perform Security/Authorization checks here
  if(!Authorized)
  {
      return Json(new {success=false, message="Access Denied"});
  }
   var model = new ViewModel();
   //Load data from database layer here
   var partialView = CreatePartialView("_editScreen", model) //helper function 
   return Json(new {success=true, content = partialView });
   
}

Is this a good practice to use in my future projects as well? I’m seeing this not only from my perspective as developer, but from the user’s as well. Because as a user its much easier for me to have everything I need on a single page without having to navigate through many pages. I’ve created this in a way that is dynamic and it can fit into all my pages and any type of data.

What are your opinions on this?

Thank you 🙂

ajax – How to close a modal with a submit form and implement a CloseModalDialogCommand?

I saw this issue here, but I wanted to post this question as the answers seem incomplete and the question is not specific to closing a modal with a submit form.

I am using a form_alter to use ajax and open up a modal dialog:

$form('actions')('submit')('#ajax') = (
  'callback' => 'my_module_form_submit',
  // prevent jump to top of page.
  'disable-refocus' => TRUE,
  'wrapper' => 'all_form',
  'effect' => 'fade',
  'progress' => (
    'type' => 'throbber',
    'message' => t('doing some work'),
  ),
);
$uses_modal = $config->get('use_modal');
if ($uses_modal) {
  $form('#attached')('library')() = 'core/drupal.dialog.ajax';
}

In the my_module_form_submit I am opening the modal:

  $title = $config->get('ajax_modal_title') ?: t('My Title!');
  $content = Drupal::formBuilder()->getForm('Drupalmy_moduleFormAjaxModalForm');
  $options = (
    'width' => $config->get('ajax_modal_width'),
    'height' => $config->get('ajax_modal_height'),
  );

  $uses_modal = $config->get('use_modal');
  if ($uses_modal) {
    $response->addCommand(new OpenModalDialogCommand($title, $content, $options));
  }

  return $response;
}

the $content = Drupal::formBuilder()->getForm('Drupalmy_moduleFormAjaxModalForm'); is pointing to a form I am building with a close button:

<?php

namespace Drupalmy_moduleForm;

use DrupalCoreFormFormBase;
use DrupalCoreFormFormStateInterface;
use DrupalCoreAjaxAjaxResponse;
use DrupalCoreAjaxReplaceCommand;
use DrupalCoreAjaxCloseModalDialogCommand;

class AjaxModalForm extends FormBase {

  /**
   * {@inheritdoc}
   */
  public function getFormId() {
    return 'ajax_modal_form';
  }

  public function buildForm(array $form, FormStateInterface $form_state) {

    $form('actions') = array('#type' => 'actions');
    $form('actions')('cancel') = (
      '#type' => 'submit',
      '#value' => $this->t('cancel'),
      '#attributes' => (
        'class' => (
          'use-ajax',
        ),
      ),
      '#ajax' => (
        'callback' => '::closeModalForm',
        'event' => 'click',
      ),
    );

    $form('#attached')('library')() = 'core/drupal.dialog.ajax';

    return $form;
  }

  public function closeModalForm(array $form, FormStateInterface $form_state) {
    $command = new CloseModalDialogCommand();
    $response = new AjaxResponse();
    $response->addCommand($command);
    return $response;
  }

  /**
   * {@inheritDoc}
   */
  public function validateForm(array &$form, FormStateInterface $form_state) {

  }

  /**
   * {@inheritdoc}
   */
  public function submitForm(array &$form, FormStateInterface $form_state) {

  }

I am doing it this way because I want to avoid using a link, and controller. The form displays as expected and debugging shows the form is built, but the callback doesn’t fire to closeModalForm.Also I get an ajax error when tryinf to close the button with the modal.

Am I going about this completely wrong? Essentially if i can get the close button to work, then i can build the form out to have more than just the button.

I put something together using a Controller, which worked:

<?php

namespace Drupalmy_moduleController;

use DrupalCoreControllerControllerBase;
use DrupalCoreAjaxCloseModalDialogCommand;
use DrupalCoreAjaxAjaxResponse;

class ModalController extends ControllerBase {

  public function closeModalForm() {
    $command = new CloseModalDialogCommand();
    $response = new AjaxResponse();
    $response->addCommand($command);
    return $response;
  }
}

And then called it like this in the $content of the OpenModalDialogCommand:

$content = (
  'message' => (
    '#markup' => t('some text'),
  ),
  'close' => (
    '#type' => 'container',
    '#markup' => t('<a class=use-ajax href=":url">@close_text</a>', (
      ':url' => Url::fromRoute('my_module.closeModal')->toString(),
      '@close_text' => $config->get('close_text') ?: t('Close'),
    )),
  ),
);

I think using the controller is a little hacky if don’t have a page destination. It creates a link that can be opened in a new tab which is a white page with the dialog command in the corner.

Ultimately I want a submit form to close the modal instead of a controller and link.

Inline editing or modal popup

I like Jon’s answer a lot.

There is another aspect to be considered – multi-record editing. Clearly, if you want to allow the user to edit multiple records at the same time, the inline method does not work. Consider iTunes, or some other (better) music ID3 tag editor. Sometimes you need to correct the name of a song – inline editing is perfect for that (though you do have the challenge of disambiguating between a click to select the record, a click to play the track, and a click to edit the specific field). Sometimes, you want to select all the tracks in an album and change the genre. For this it’s nice to multi-select the rows and then invoke an editor dialog (CMD+I does it in iTunes) where you can then fill in one or multiple fields and only those fields will then be updated for the entire record. (iTunes’ implementation of this, while functional, is not immediately intuitive).

From the perspective of the developer, if you have a limited amount of time and can only implement one input method, you need to consider whether you’re going to launch with multi-record editing enabled or not. If you will, then opt for the dialog: you take a bit of a usability and performance hit, but you can save yourself a ton of time coding.

I hate to say this, but if we’re just sticking to those two ways of handling input, your best bet is to implement them both, and find an intuitive way (better than itunes at any rate) to allow the user to enter into inline editing mode (Microsoft’s F2 is the pits too, though at least they’re fairly consistent about it), and for the user to enter into multi-record mode.

One last thing to consider: for inline editing to work, you need to have visibility into all fields of the record in your tabular display. If you’re allowing your users to hide columns, or are only choosing to show a subset of the editable fields, you have no choice but to implement some kind of editable “detail view”.

php – Enviar ID, hacer una consulta y reflejar datos en modal bootstrap

Estoy diseñando un dashboard y creé una tabla donde trae datos de diferentes personas. Estoy tratando de hacer que la tabla se lleve el “NUMDOC” de cada persona a través de un botón, para que con ese “NUMDOC” traiga datos de otra tabla.
El problema, es que a la hora de hacer clic en el botón, únicamente me aparece el “backdrop” del modal de Bootstrap.

Imagen a modo de ilustración. El ojo representaría el botón que está puesto actualmente en el código.
Imagen a modo de ilustración. El ojo representaría el botón que está puesto actualmente en el código. La idea es que se entienda un poco mejor cómo aparece en la tabla. Reflejará solo 5 resultados ya que tiene un LIMIT en la consulta $sql.

Primeramente, voy a compartir el código de mi tabla con su consulta php:

Consulta PHP

<?php   
        require_once 'controllers/connection.php';
        error_reporting(E_ALL);
              
          define("ROW_PER_PAGE",2);

            $search_keyword = '';
              if(!empty($_POST('search')('keyword'))) {
                $search_keyword = $_POST('search')('keyword');
              }
            $sql = 'SELECT * FROM padronint WHERE nombre LIKE :keyword OR numdoc LIKE :keyword OR domicilio LIKE :keyword OR telefono LIKE :keyword LIMIT 5;';
        
            /* Pagination Code starts */
            $per_page_html = '';
            $page = 1;
            $start=0;
              if(!empty($_POST("page"))) {
                $page = $_POST("page");
                $start=($page-1) * ROW_PER_PAGE;
              }
            $limit=" limit " . $start . "," . ROW_PER_PAGE;
            $pagination_statement = $connect->prepare($sql);
            $pagination_statement->bindValue(':keyword', '%' . $search_keyword . '%', PDO::PARAM_STR);
            $pagination_statement->execute();
        
            $row_count = $pagination_statement->rowCount();
              if(!empty($row_count)){
                $per_page_html .= "<div style='text-align:center;margin:20px 0px;'>";
                $page_count=ceil($row_count/ROW_PER_PAGE);
                if($page_count>1) {
                    for($i=1;$i<=$page_count;$i++){
                        if($i==$page){ //<li class="page-item active"><a href="#" class="page-link">1</a></li>
                            $per_page_html .= '<li class="page-item"><input type="submit" name="page" value="' . $i . '" class="page-link" /></li>';
                        } else {
                            $per_page_html .= '<li class="page-item"><input type="submit" name="page" value="' . $i . '" class="page-link" /></li>';
                        }
                    }
                }
                $per_page_html .= "</div>";
              }
        
            $query = $sql.$limit;
            $pdo_statement = $connect->prepare($query);
            $pdo_statement->bindValue(':keyword', '%' . $search_keyword . '%', PDO::PARAM_STR);
            $pdo_statement->execute();
            $result = $pdo_statement->fetchAll(PDO::FETCH_ASSOC);
      ?>

Tabla HTML QUE MUESTRA LOS RESULTADOS DE DICHA CONSULTA

      <form name="frmSearch" class="" action="" method="post">
    <div class="table-responsive">
        <div class="table-wrapper">
            <div class="table-title">
                <div class="row">
                    <div class="col-sm-8"><h2>Tabla <b>Internados</b></h2></div>
                    <div class="col-sm-4">
                        <div class="search-box">
                            <input type="text" name="search(keyword)" class="form-control" placeholder="Buscar&hellip;" value="<?php echo $search_keyword; ?>" id='keyword' maxlength='25'>
                        </div>
                    </div>
                </div>
            </div>
            <!-- GUARDADO DE DATOS -->

            <table class="table table-striped table-hover table-bordered">
                <thead>
                    <tr>
                        <th>Nombre</th>
                        <th>DNI<i class="fa fa-sort"></i></th>
                        <th>Domicilio</th>
                        <th>Telefono</th>
                        <th>Acciones</th>
                    </tr>
                </thead>
                <tbody>
                  <?php if (empty($result) === false): ?>
                    <?php foreach($result as $row): ?>
                      <tr>
                        <td><?= htmlspecialchars($row('nombre')) ?></td>
                        <td><?= htmlspecialchars($row('numdoc')) ?></td>
                        <td><?= htmlspecialchars($row('domicilio')) ?></td>
                        <td><?= htmlspecialchars($row('telefono')) ?></td>
                        <td><?= '<button data-bs-toggle="modal" data-bs-target="#getuser" data-id="<?php echo $row("numdoc")?>" id="getUser" class="btn btn-sm btn-info">Ver</button>'; ?>
                        <i class="fa-solid fa-eye">
                          <!--<a href="#" class="edit" title="Edit" data-toggle="tooltip"><i class="material-icons">&#xE254;</i></a>
                          <a href="#" class="delete" title="Delete" data-toggle="tooltip"><i class="material-icons">&#xE872;</i></a>-->
                        </td>
                      </tr>
                    <?php endforeach; ?>
                  <?php endif; ?>
                </tbody>
            </table>
            <script>
                        $('#getuser').on('show.bs.modal', function (event) {
                          var button = $(event.relatedTarget) // Button that triggered the modal
                          var recipient = button.data('whatever') // Extract info from data-* attributes
                          var modal = $(this);
                          var dataString = 'id=' + recipient;

                          $.ajax({
                            type: "GET",
                            url: "controllers/modalc.php",
                            data: dataString,
                            cache: false,
                            success: function (data) {
                                console.log(data);
                                modal.find('.dash').html(data);
                            },
                            error: function(err) {
                                console.log(err);
                           }
                       });
                       })              
            </script>
            <div class="clearfix">
                <!-- <div class="hint-text">Showing <b>5</b> out of <b>25</b> entries</div> -->
                <ul class="pagination">
                    <li class="page-item"><a href="#" class="page-link"><i class="fa-solid fa-left-from-line"></i></a></li>
                    <?php echo $per_page_html; ?>
                    <!--
                    <li class="page-item active"><a href="#" class="page-link">1</a></li>
                    <li class="page-item"><a href="#" class="page-link">2</a></li>
                    <li class="page-item"><a href="#" class="page-link">3</a></li>
                    <li class="page-item"><a href="#" class="page-link">4</a></li>
                    <li class="page-item"><a href="#" class="page-link">5</a></li>-->
                    <li class="page-item"><a href="#" class="page-link"><i class="fa-solid fa-right-from-line"></i></a></li>
                </ul>
            </div>
        </div>
    </div> 
  </form>

SCRIPT QUE ALMACENA EL “NUMDOC” DE CADA PERSONA QUE APARECE EN LA TABLA

                <script>
                        $('#getuser').on('show.bs.modal', function (event) {
                          var button = $(event.relatedTarget) // Button that triggered the modal
                          var recipient = button.data('whatever') // Extract info from data-* attributes
                          var modal = $(this);
                          var dataString = 'id=' + recipient;

                          $.ajax({
                            type: "GET",
                            url: "controllers/modalc.php",
                            data: dataString,
                            cache: false,
                            success: function (data) {
                                console.log(data);
                                modal.find('.dash').html(data);
                            },
                            error: function(err) {
                                console.log(err);
                           }
                       });
                       })              
            </script>

Como se ve en el script, técnicamente solicita un archivo dentro de la carpeta “controllers”, llamado “modalc.php”. Este archivo es usar el ID que guarda el AJAX y simplemente hacer la consulta para que distribuya los datos en el modal, comparto el código a continuación:

CÓDIGO PHP DEL ARCHIVO MODALC.PHP

    <?php 

include('connection.php');

if(isset($_GET("numdoc")))
{
 $query = "SELECT * FROM internacion, padronint WHERE historia = '".$_GET("numdoc")."'";

 $statement = $connect->prepare($query);
 $statement->execute();
 $result = $statement->fetchAll();
 $output = '<div class="row">';
 foreach($result as $row)
 {
  $output .= '
  <div class="col-md-9">
   <br />
   <p><label>Nombre :&nbsp;</label>'.$row("nombre").'</p>
   <p><label>Nro Int. :&nbsp;</label>'.$row("nro_internacion").'</p>
   <p><label>Telcod :&nbsp;</label>'.$row("telcod").'</p>
   <p><label>Nomgar :&nbsp;</label>'.$row("nomgar").'</p>
   <p><label>Usuario :&nbsp;</label>'.$row("usuario").' years</p>
  </div>
  </div><br />
  ';
 }
 echo $output;
}

?>

CÓDIGO DEL MODAL UTILIZADO EN ESTE SISTEMA (BOOTSTRAP)

<!-- Modal -->
<div class="modal fade" id="getuser" data-bs-backdrop="static" data-bs-keyboard="false" tabindex="-1" aria-labelledby="staticBackdropLabel" aria-hidden="true">
  <div class="modal-dialog modal-dialog-centered">
    <div class="modal-content">
      <div class="modal-header">
        <h5 class="modal-title" id="staticBackdropLabel">Modal title</h5>
        <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
      </div>
      <div class="modal-body">
        ...
      </div>
      <div class="modal-footer">
        <button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
        <button type="button" class="btn btn-primary">Understood</button>
      </div>
    </div>
  </div>
</div>

En este sistema estoy utilizando: Bootstrap, jQuery, Ajax, MySQL, PHP (PDO).