Есть задача — с помощью чистого JavaScript реализовать динамическое создание полей ввода и добавление их в список. Например, это может понадобиться при составлении списка покупок/студентов или чего-то подобного.
При решении данной задачи Вам потребуются следующие знания:
- Поиск элемента по селектору;
- Отслеживание клика по элементу;
- Клонирование элемента со всем содержимым;
- Добавление и удаление классов;
- Отслеживание клика по динамически созданному элементу;
- Определение ближайшего элемента с указанным селектором;
- Удаление элемента.
Решение
Для решения задачи необходимо заверстать элемент, который будет использован как образец для создания элементов списка.
1 2 3 4 5 6 7 8 | <div class="example_student"> <div class="table"> <div class="cell"><input class="form-control" type="text" name="name[]"/></div> <div class="cell"> <button class="js-remove pull-right btn btn-danger">-</button> </div> </div> </div> |
Обратите внимание, что имя поля input
я указываю с квадратными скобками — name[]
, так как полей будет больше одного, то при отсутствии квадратных скобок будет передано только значение последнего поля, а необходимо передавать значения каждого поля, поэтому ставятся квадратные скобки, говорящие что значение поля является элементом массива name
.
Далее я буду брать этот код как объект и изменяя его вставлять в список.
Эти действия необходимо совершать при клике по кнопке с плюсом.
1 2 3 4 5 6 7 | // определение кнопки добавления var button_add = document.querySelector( '.dynamic_fields .js-add' ); // ожидание клика на кнопку .add button_add.addEventListener( "click", function () { // какие-то действия } |
После того, как событие клика произошло необходимо определить список, в который будет помещен элемент, определить и клонировать элемент списка, изменить в нем класс(обратите внимание, что изменение класса происходит по средствам добавления нового и удаления старого класса) и добавить элемент в список.
Под списком я понимаю не комбинацию тегов
ul > li
, а логически связанные между собой блоки, содержащие поля ввода.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | // определение блока, содержащего элементы var students = document.querySelector( '.dynamic_fields .students' ); // клонирование образцового элемента var element = document.querySelector( '.example_student' ).cloneNode( true ); // добавление класса к клонированному элементу element.classList.add( 'student' ); // удаление класса из клонированного элемента element.classList.remove( 'example_student' ); // добавление нового элемента к списку students.appendChild( element ); |
После этого можно приступить к удалению элемента списка. Для этого потребуется отловить событие клика на кнопке, которой не существовало в момент создания страницы, которая была создана при добавлении клонированного блока в список.
Чтобы поймать событие динамически созданного элемента необходимо ожидать клик не по элементу, а по всему документу, а лишь затем определять куда пришелся клик.
1 2 3 4 | // ожидание клика по документу document.addEventListener( "click", function ( el ) { // какие-то действия } |
Необходимо понять был ли клик совершен по элементу и если да, содержал ли элемент класс js-remove
:
1 2 3 4 | // если клик был по элементу, который содержит класс remove if ( el.target && el.target.classList.contains( 'js-remove' ) ) { // какие-то действия } |
Далее необходимо определить прародительский блок, который содержит кнопку по которой был произведен клик и другие связанные элементы, фактически необходимо выяснить в каком из клонированных ранее блоков содержится кнопка по которой был произведен клик.
1 | var child = el.target.closest( '.table' ); |
После того, как блок, элемент списка, определен его следует удалить. Чтобы его удалить необходимо сперва определить родительский элемент, а затем в родительском элементе удалить тот, который необходимо, указав его как дочерний.
1 | child.parentNode.removeChild( child ); |
Результат решения задачи