javascriptc#jquerytwitter-bootstrapasp.net-core-mvc

Passing entity model data into Bootstrap Modal


I'm trying to pass data to a modal. After searching around the internet and following bootstrap I found a couple of ways. 1) is by passing the model through data-bs-whatever="@Model", however, if try to access it by recipient (see below) and find its properties it gives me undefined. 2) I can pass the Id of the product by adding this line of code data-id="@Modal.EntityId", however if I follow that way I have to make an AJAX call which I find it unnecessary. How can I pass an entity with fields like; Id, Name, Number, etc. to the bootstrap modal?

Technologies: .NET 8 MVC, Bootstrap 5

Code as follows:


<table id="entities" class="table table-striped">
    <thead>
        <tr>
            <th scope="col">#</th>
            <th scope="col">Product Name</th>
            <th scope="col">Part Number</th>
            <th scope="col">Actions</th>
        </tr>
    </thead>
    <tbody>
        @foreach(Entity ent in @Model.Entities)
        {
            <tr>
                <td>@ent.Id</td>
                <td>@ent.Name</td>
                <td>@ent.Number</td>
                <td>
                    // Other Actions
                    <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-whatever="@ent">Remove</button>
                </td>
            </tr>
        }
    </tbody>
</table>

<!-- Modal -->
<!-- Want to access the complete entity in the modal if possible -->
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
    <div class="modal-dialog">
        <div class="modal-content">
            <div class="modal-header">
                <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
                <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
            </div>
            <div class="modal-body">
                <p></p>
            </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">Save changes</button>
            </div>
        </div>
    </div>
</div>

<script type="text/javascript">
    $(document).ready(function (){
        $('#products').DataTable();
        $('#clients').DataTable();
    })

    const exampleModal = document.getElementById('exampleModal')
    exampleModal.addEventListener('show.bs.modal', event => {
        const button = event.relatedTarget
        const recipient = button.getAttribute('data-bs-whatever')

        console.log(recipient.Name) // Accessing the property of recipient is undefined
        console.log(recipient) // This logs back the entity type
        const modalTitle = exampleModal.querySelector('.modal-title')
        const modalBodyInput = exampleModal.querySelector('.modal-body p')

        modalTitle.textContent = `Warning! You're about to remove ${recipient}`
        modalBodyInput.textContent = recipient.Name
    })
</script>


Solution

  • The key to solving this problem is to serialize the C# object into a JSON string and store it in the data property, and then parse the string into an object in JS to access the properties.

    enter image description here

    My test code

    @{
        ViewData["Title"] = "Home Page";
    }
    
    <script src="https://cdn.datatables.net/2.2.2/js/dataTables.min.js"></script>
    <script src="https://cdn.datatables.net/2.2.2/js/dataTables.bootstrap5.min.js"></script>
    
    <table id="entities" class="table table-striped">
        <thead>
            <tr>
                <th scope="col">#</th>
                <th scope="col">Product Name</th>
                <th scope="col">Part Number</th>
                <th scope="col">Actions</th>
            </tr>
        </thead>
        <tbody>
            @foreach (Entity ent in @Model.Entities)
            {
                <tr>
                    <td>@ent.Id</td>
                    <td>@ent.Name</td>
                    <td>@ent.Number</td>
                    <td>
                        @* // Other Actions *@
                        <button class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal" data-bs-entity='@Html.Raw(Json.Serialize(ent))'>Remove</button>
                    </td>
                </tr>
            }
        </tbody>
    </table>
    
    <!-- Modal -->
    <!-- Want to access the complete entity in the modal if possible -->
    <div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
        <div class="modal-dialog">
            <div class="modal-content">
                <div class="modal-header">
                    <h1 class="modal-title fs-5" id="exampleModalLabel">Modal title</h1>
                    <button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
                </div>
                <div class="modal-body">
                    <p></p>
                </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">Save changes</button>
                </div>
            </div>
        </div>
    </div>
    
    <script type="text/javascript">
        $(document).ready(function (){
            $('#products').DataTable();
            $('#clients').DataTable();
        })
    
        const exampleModal = document.getElementById('exampleModal')
        exampleModal.addEventListener('show.bs.modal', event => {
            const button = event.relatedTarget;
            debugger
            // keyponit
            const recipientJson = button.getAttribute('data-bs-entity');
            const recipient = JSON.parse(recipientJson)
    
            console.log(recipient.name) // Accessing the property of recipient is undefined
            console.log(recipient) // This logs back the entity type
            const modalTitle = exampleModal.querySelector('.modal-title')
            const modalBodyInput = exampleModal.querySelector('.modal-body p')
    
            modalTitle.textContent = `Warning! You're about to remove ${recipient.name}`
            modalBodyInput.textContent = recipient.name
        })
    </script>
    

    HomeController/Index

        public IActionResult Index()
        {
            var model = new
            {
                Entities = new List<Entity> {
                    new Entity { Id = 1, Name = "PRODUCT A", Number = "P-001" },
                    new Entity { Id = 2, Name = "PRODUCT B", Number = "P-002" }
                }
            };
            return View(model);
        }