jQuery Repeater doesn't work in a partial generated with ajax

4k Views Asked by At

In a form consisting of several steps generated in ajax within a single page, I have to use jquery.repeater in an intermediate step.

The form code specific to the repeater is in a dedicated partial

But jquery.repeater does not work, nothing happends when i click on the add or the delete buttons, without even a single javascript error message in the console.

It works if I use this partial directly in a page without the ajax loading.

Note i use the pushing partial updates method in my ajax handler method with

return [ '#myDiv' => $this->renderPartial('mypartial') ];

Welcome for help mates.

here the code i use

and scripts declaration in the bottom of my layout

...
<!-- Scripts -->
<script src="{{ [
    'assets/javascript/jquery-3.2.1.min.js',
]|theme }}"></script>
{% framework extra %}
{% scripts %}
</body>
</html>

my partial

<form class="repeater">
    <!--
        The value given to the data-repeater-list attribute will be used as the
        base of rewritten name attributes.  In this example, the first
        data-repeater-item's name attribute would become group-a[0][text-input],
        and the second data-repeater-item would become group-a[1][text-input]
    -->
    <div data-repeater-list="group-a">

      <div data-repeater-item style="display:none;">
        <input type="text" name="text-input" />
        <input data-repeater-delete type="button" value="Delete" />
      </div>

      <div data-repeater-item>
        <input type="text" name="text-input" />
        <input data-repeater-delete type="button" value="Delete" />
      </div>

    </div>

    <input data-repeater-create type="button" value="Add" />
</form>

my page

title = "Ajouter"
url = "/tableau-de-bord/espace/ajouter"
layout = "dashboard"
is_hidden = 0

[formulaireCreation]
==
function onStart()
{
    $this->addJs('assets/javascript/node_modules/jquery.repeater/jquery.repeater.js');
    $this->addJs('assets/javascript/my-repeater.js');
}
==
<div id='formulaire-creation-component-wrapper'>
    {% component 'formulaireCreation' %}
</div>

my-repeater.js

$(document).ready(function () {
    $('.repeater').repeater({

        // (Optional)
        // "show" is called just after an item is added.  The item is hidden
        // at this point.  If a show callback is not given the item will
        // have $(this).show() called on it.
        show: function () {
            $(this).slideDown();
        },
        // (Optional)
        // "hide" is called when a user clicks on a data-repeater-delete
        // element.  The item is still visible.  "hide" is passed a function
        // as its first argument which will properly remove the item.
        // "hide" allows for a confirmation step, to send a delete request
        // to the server, etc.  If a hide callback is not given the item
        // will be deleted.
        hide: function (deleteElement) {
            if(confirm('Are you sure you want to delete this element?')) {
                $(this).slideUp(deleteElement);
            }
        },
    })
});

And finally, for comparison, the code that works in a basic page

title = "repeater-test"
url = "/repeater-test"
layout = "dashboard"
is_hidden = 0
==
function onStart()
{
    $this->addJs('assets/javascript/node_modules/jquery.repeater/jquery.repeater.min.js');
    $this->addJs('assets/javascript/my-repeater.js');
}
==
<form class="repeater">

    <div data-repeater-list="group-a">

      <div data-repeater-item style="display:none;">
        <input type="text" name="text-input" />
        <input data-repeater-delete type="button" value="Delete" />
      </div>

      <div data-repeater-item>
        <input type="text" name="text-input" />
        <input data-repeater-delete type="button" value="Delete" />
      </div>

    </div>

    <input data-repeater-create type="button" value="Add" />

</form>
2

There are 2 best solutions below

5
On

ok i found a solution, not very elegant but it works

when the partial with the repeater is loaded in ajax, It is as if the page forgot the script declared with addJS at the page level, so I declared the script using <script src="/path/to/myscript.js"> at the end of the partial directly and it works

tried to inject the script with {% put scripts %} but doesn't work

0
On

Working with JqueryRepeater is like working in hell. Visually it is fantastic but coding something other than the basic is like a kick in the -gg- everytime!

It seems that jQuery don't detect well the new fields of each row, but working with pure JavaScript is possible.

For example, to change the value of a new generated input...

Document. getElementsByName ( "your-data-repeater-list[1][field_name]")[0].Value =  "My new value";

Where [1] is the new repeater num

I have spent several days (and nights!) working with this component and with some patience it is possible to do whatever you want.

Have fun!