Need help with forms inside of table repeats

Hi,

I’ve been trying to work this out for a couple of hours now, but I’m having some problems getting this to work.

I currently have a bootstrap table with dynamic data from a server action, this all works fine. I have now built an editor into this table, so when you click to edit the fields change on that particular line to this:

When clicking save, I need it to submit a form. The problem is I can’t figure out how to submit a form for all of the columns at once in a single row. From what I can work out the form has to start above the table (before <table class="table align-middle table-nowrap table-hover">), but submitting this form sends it for each row when I only want it to submit for the row edited. How can I achieve this?

I’ve done this a few ways before.

The first, was to simply ignore the best practice (or perhaps even requirement) that the form element had to be outside the table. I have a working project where I manually placed a <form ...> inside a table cell, and then inside that form, I created another table with inputs, etc. This can work, but really is not ideal and may even break in some browsers.

The second way is to use css grids instead of tables. You can google all sorts of solutions on this, but there isn’t anything in wappler natively. I really like CSS grids, but it becomes manual work at this stage.

However, I think the best solution for Wappler today is…

To maintain your forms outside of the the table structure altogether. Your inputs would be inside the table, but your form would not. Each of the inputs then gets a form attribute that points to the id of the intended form.

Take this working example.

There is a server connect that has the items we want to repeat over.

Inside the first container, there is all the content that will be displayed to the user. There is a row that repeats using the serverconnect data array of “cars”. It has inputs inside the table structure, but there is no form.

In the second container, there is another repeat of the same data “cars”, but this time we are creating a form with nothing inside of it.

The inputs inside the table get a dynamic form attribute that matches the dynamic form id. I’m using the index of the repeats to keep everything in sync.

<dmx-serverconnect id="serverconnect1" url="api/output_repeat"></dmx-serverconnect>
<div class="container">
    <div class="table-responsive">
        <table class="table">
            <thead>
                <tr>

                    <th scope="col">Text input</th>
                    <th scope="col">Select</th>
                    <th scope="col">File upload</th>
                    <th scope="col">Submit button</th>
                </tr>
            </thead>
            <tbody>
                <tr dmx-repeat:each_car="serverconnect1.data.cars">


                    <td>
                        <input id="text1" name="text1" type="text" class="form-control" dmx-bind:form="my_form_{{$index}}">
                    </td>
                    <td>
                        <select id="select1" class="form-select" dmx-bind:form="my_form_{{$index}}" name="select">
                            <option value="1">Option One</option>
                            <option value="2">Option Two</option>
                            <option value="3">Option Three</option>
                        </select>
                    </td>
                    <td class="text-center">
                        <input type="file" class="form-control visually-hidden" dmx-bind:id="file_input_{{$index}}" name="myfile" aria-describedby="input1_help" dmx-bind:form="my_form_{{$index}}">
                        <label dmx-bind:for="file_input_{{$index}}" class="form-label">
                            <i class="fas fa-cloud-upload-alt"></i>
                        </label>


                    </td>
                    <td>
                        <a href="#" class="btn" dmx-on:click="data_forms[$index].my_form.submit(true)">Save</a>
                    </td>

                </tr>
            </tbody>
        </table>
    </div>
</div>
<div class="container visually-hidden">
    <div dmx-repeat:data_forms="serverconnect1.data.cars">
        <form dmx-bind:id="my_form_{{$index}}" id="my_form" is="dmx-serverconnect-form" method="post" action="api/form_save">

        </form>
    </div>
</div>

EDIT: I added a file input into the mix.

3 Likes

Thank you! Using the {{$index}} was exactly what I needed to get this working. I did do it slightly differently from how you had, though.

Instead of putting a repeat form further down the page, I simply add a new column to the table and made it visually hiden. This column contained a form with dmx-bind:id=“tableedit_{{$index}}”. I then had a button with the same:

<button type="submit" class="btn btn-warning waves-effect waves-light w-sm" dmx-show="(edittoggle.value == 1)" dmx-bind:form="tableedit_{{$index}}">
     <i class="mdi mdi-marker d-block font-size-16"></i> Save
</button>

This is now working perfectly and I have a working table with an editing function, thanks for your help!

1 Like