jQuery: моя функция click-event-method вводится только для некоторых кнопок, хотя все они имеют один и тот же класс

#javascript #html #jquery

#javascript #HTML #jquery

Вопрос:

У меня есть несколько форм, отрисованных из Django modelFormset. Для каждой формы я создаю кнопку «Вставить» рядом с ней, чтобы добавить новую форму после нее. Когда я загружаю страницу, формы отображаются из строк базы данных, затем я нажимаю на любую кнопку insert и добавляется моя новая форма. Теперь, когда я нажимаю на кнопку insert, которая находится рядом с этой недавно созданной формой, ничего не происходит, функция внутри моего метода click-event даже не вводится. Все эти кнопки имеют один и тот же класс.

Я создаю новую форму, клонируя элемент div, который его содержит, затем изменяя его атрибуты, а затем вставляя его.

Вот как выглядит мой шаблон перед добавлением новой формы. У меня сейчас есть только две строки в моей таблице базы данных, которые я создал вручную для тестирования.

 <body>
    <form method="POST" class="note-form">
        <input type="hidden" name="csrfmiddlewaretoken" ...>
        <div class="notes-pane">
            <div id="management-form">...<div>
            </div>
            <div class="note" id="id-note-1">
                <input type="number" name="form-0-note_number" value="1" class="disabled" readonly="readonly" id="id_form-0-note_number">
                <textarea name="form-0-note_text" cols="100" rows="8" id="id_form-0-note_text">This is the first note</textarea>
                <button id="ins-after-1" class="ins-note-after" type="button" value="ins-after-1">Insert</button>
                <input type="hidden" name="form-0-id" value="60" id="id_form-0-id">
            </div>
            <div class="note" id="id-note-2">
                <input type="number" name="form-1-note_number" value="2" class="disabled" readonly="readonly" id="id_form-1-note_number">
                <textarea name="form-1-note_text" cols="100" rows="8" id="id_form-1-note_text">This is the second note</textarea>
                <button id="ins-after-2" class="ins-note-after" type="button" value="ins-after-2">Insert</button>
                <input type="hidden" name="form-1-id" value="61" id="id_form-1-id">
            </div>
        </div>
    </form>
</body>
  

Это мой JavaScript для добавления кнопок в форму и создания новых форм.
Вероятно, это не очень чисто. Я все еще новичок в JavaScript.

 <script>
    $(document).ready(function() {
        //------------------------------------------------------------------
        //--------------------ADDING INSERT-NOTE BUTTONS--------------------
        var noteFormList = $(".note").find("textarea");

        for (noteElement of noteFormList) {
            var buttonNumber = Number(noteElement.id.match(/d /)) 1
            var newButton = $("<button></button>").text("Insert");
            newButton.attr("id", "ins-after-" buttonNumber);
            newButton.attr("class", "ins-note-after");
            newButton.attr("type", "button");
            newButton.attr("value", "ins-after-" buttonNumber);
            $("#" noteElement.id).after(newButton);
            
        }

        //------------------------------------------------------------------
        //----------------------INSERTING A NEW NOTE------------------------

        $(".ins-note-after").click(function() {
            var insertAfter = $(this).attr("value").match(/d /)[0];
            // To see if the function is entered.
            console.log(insertAfter);
            console.log("Inserting note after " insertAfter);
            
            // Update the total and initial forms in the management form.
            var newTotalForms = $("#id_form-TOTAL_FORMS").attr("value");
            newTotalForms  ;
            $("#id_form-TOTAL_FORMS").attr("value", newTotalForms);
            $("#id_form-INITIAL_FORMS").attr("value", newTotalForms);

            // Getting the list of notes that need to be moved.
            // They're not moved, actually, only their indexes/numbers are changed.
            var notesToMove = $(".note").filter(function() {
                return this.id.match(/d /) > insertAfter
            });
            var newNote;
            var noteNumberToMod;
            var textareaToMod;
            var buttonToMod;
            var idToMod;

            // This is executed when the note will be inserted between notes.
            if (notesToMove.length > 0) {

                // Clone the first note that will be moved.
                // The insertion will be made from this one.
                newNote = $(notesToMove[0]).clone();
                newNote.find("textarea").text("");
                // Insert the new note form where it corresponds.
                $("#id-note-" insertAfter).after(newNote);
                var changeIndex = Number(insertAfter);
                
                // Modify the attributes of every single note form
                // after the inserted one.
                for (note of notesToMove) {
                    note.id = "id-note-" (changeIndex 2);
                    noteNumberToMod = $(note).find("#id_form-" changeIndex "-note_number");
                    textareaToMod = $(note).find("#id_form-" changeIndex "-note_text");
                    buttonToMod = $(note).find("#ins-after-" (changeIndex 1));
                    idToMod = $(note).find("#id_form-" changeIndex "-id");

                    noteNumberToMod.attr("name", "form-" (changeIndex 1) "-note_number");
                    noteNumberToMod.attr("value", (changeIndex 2));
                    noteNumberToMod.attr("id", "id_form-" (changeIndex 1) "-note_number");
                    textareaToMod.attr("name", "form-" (changeIndex 1) "-note_text");
                    textareaToMod.attr("id", "id_form-" (changeIndex 1) "-note_text");
                    buttonToMod.attr("id", "ins-after-" (changeIndex 2));
                    buttonToMod.attr("value", "ins-after-" (changeIndex 2));
                    idToMod.attr("name", "form-" (changeIndex 1) "-id");
                    idToMod.attr("id", "id_form-" (changeIndex 1) "-id");
                    idToMod.attr("value", "");

                    changeIndex  ;


                }
            // This is executed when the insertion is after the last note.
            } else {
                var insAfter = Number(insertAfter);
                newNote = $("#id-note-" insAfter).clone();
                insAfter--;
                noteNumberToMod = newNote.find("#id_form-" insAfter "-note_number");
                textareaToMod = newNote.find("#id_form-" insAfter "-note_text");
                buttonToMod = newNote.find("#ins-after-" (insAfter 1));
                idToMod = newNote.find("#id_form-" insAfter "-id");

                newNote.attr("id", "id-note-" (insAfter 2));
                noteNumberToMod.attr("name", "form-" (insAfter 1) "-note_number");
                noteNumberToMod.attr("value", (insAfter 2));
                noteNumberToMod.attr("id", "id_form-" (insAfter 1) "-note_number");
                textareaToMod.attr("name", "form-" (insAfter 1) "-note_text");
                textareaToMod.attr("id", "id_form-" (insAfter 1) "-note_text");
                buttonToMod.attr("id", "ins-after-" (insAfter 2));
                buttonToMod.attr("value", "ins-after-" (insAfter 2));
                idToMod.attr("name", "form-" (insAfter 1) "-id");
                idToMod.attr("id", "id_form-" (insAfter 1) "-id");
                idToMod.attr("value", "");
                newNote.find("textarea").text("");

                $("#id-note-" (insAfter 1)).after(newNote);

            }
    }
</script>
  

После нажатия на любую из этих двух кнопок новая форма добавляется должным образом. Вот так:
(Пожалуйста, смотрите Комментарии)

 <body>
    <form method="POST" class="note-form">
        <input type="hidden" name="csrfmiddlewaretoken" ...>
        <div class="notes-pane">
            <div id="management-form">...<div>
            </div>
            <div class="note" id="id-note-1">
                <input type="number" name="form-0-note_number" value="1" class="disabled" readonly="readonly" id="id_form-0-note_number">
                <textarea name="form-0-note_text" cols="100" rows="8" id="id_form-0-note_text">This is the first note</textarea>
                <button id="ins-after-1" class="ins-note-after" type="button" value="ins-after-1">Insert</button>
                <input type="hidden" name="form-0-id" value="60" id="id_form-0-id">
            </div>
            <div class="note" id="id-note-2">
                <input type="number" name="form-1-note_number" value="2" class="disabled" readonly="readonly" id="id_form-1-note_number">
                <!-- The textarea is empty because this is the new note that was added, after the first one-->
                <textarea name="form-1-note_text" cols="100" rows="8" id="id_form-1-note_text"></textarea>
                <button id="ins-after-2" class="ins-note-after" type="button" value="ins-after-2">Insert</button>
                <input type="hidden" name="form-1-id" value="61" id="id_form-1-id">
            </div>
            <div class="note" id="id-note-3">
                <input type="number" name="form-2-note_number" value="3" class="disabled" readonly="readonly" id="id_form-2-note_number">
                <!-- This one says "This is the second note" because it was moved after inserting one before it-->
                <textarea name="form-2-note_text" cols="100" rows="8" id="id_form-2-note_text">This is the second note</textarea>
                <button id="ins-after-3" class="ins-note-after" type="button" value="ins-after-3">Insert</button>
                <!-- Don't mind this line. I still don't know how to handle it's value-->
                <input type="hidden" name="form-2-id" value id="id_form-2-id">
            </div>
        </div>
    </form>
</body>
  

Я могу снова нажать кнопку insert на первой заметке, и после нее будет добавлена еще одна новая заметка, или на последней заметке, и после нее тоже будет добавлена новая заметка. Проблема заключается в том, что при нажатии на кнопки заметок, которые были добавлены с помощью этого кода. Ничего не происходит, функция не введена. Я удостоверяюсь, что их класс точно такой же, но, тем не менее, функция даже не введена.

Комментарии:

1. измените $(".ins-note-after").click(function() { на $(document).on('click', '.ins-not-after', () => {

2. рекомендация функции с жирной стрелкой @fedesc never идеально подходит для использования в jQuery. Поскольку она не распознает $(this) , и OP опубликует другой вопрос по этому поводу!

3. Правильно. Сила привычки 😀 … Просто хотел указать на изменение в событии click. вы правы -> $(document).on('click', '.ins-not-after', function () {

4. @fedesc Отлично. Это работает. Я читаю о разнице между использованием $().click() и $().on(click, ...) , и теперь ясно, что первое не будет работать для динамически создаваемых элементов. Но разве первые две кнопки не создаются также динамически? Они не существовали при первой загрузке страницы.

5.@TheSprinter В вашем 1-м блоке кода вы начинаете с двух кнопок. id="ins-after-1" id="ins-after-2"