Не удаляется последний элемент
Привет всем! Есть задача: форма, которая должна изменяться при добавлении новых блоков по нажатию кнопки "Добавить"/"Добавить ещё". Блоки также могут удаляться по клику на "Удалить". Поскольку в JS новичок, делал так: в разметке только один блок с адресом, который скрывал классом. При первичной загрузке страницы и нажатии на "Добавить" снимал этот класс, а остальные блоки делал путём клонирования и вставки элемента в низ родителя при нажатии "Добавить ещё". Аналогично удаление делал до 1 блока с адресом, а последний пытался скрыть, вновь навешивая класс с display: none; Но вот проблема: если удалять блоки не с последнего до первого, а в другом любом порядке, то почему-то оставшийся один блок не скрывается никак (( не могу понять почему. И ещё хотел бы спросить:
1. Как вообще правильно делаются такие вещи - создание одинаковых блоков на странице по клике с 0 до любого числа? Мне кажется, что моя идея - первый просто скрывать и открывать, а остальные делать через JS клонированием - не очень хороша; 2. Ещё, при клонировании по нажатию кнопок "Добавить" в новом блоке появляются совпадающие id, name, for у элементов формы, что не разрешается! Как сделать, чтобы они менялись? P.S. Прошу прощения за стили - брал файлы из проекта, там на препроцессоре написано и т.д., поэтому сюда в стили взял только класс, который скрывает блоки. Он назван некорректно, но пример работает. Спасибо всем, кто откликнется. <!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <link rel="stylesheet" href="css/style.css"> </head> <body> <form class="lk-address-form js-lk-address-form" action="javascript:;" method="get"> <h2 class="lk-address-form__title">Мои адреса</h2> <p class="lk-address-form__no-address js-lk-no-address">Вы не добавили еще ни одного адреса.</p> <div class="lk-address-form__container js-lk-address-container"> <div class="lk-address-form__one-address visually-hidden js-lk-one-address"> <div class="lk-address-form__address-top"> <div class="lk-address-form__address-type-toggle"> <span class="lk-address-form__address-type">Тип адреса: </span> <div class="input-radio"> <input class="input-radio__input" type="radio" id="work-address" name="address-type"> <label class="input-radio__label" for="work-address">Рабочий</label> </div> <div class="input-radio"> <input class="input-radio__input" type="radio" id="home-address" name="address-type"> <label class="input-radio__label" for="home-address">Домашний</label> </div> </div> <a class="link link--colored visually-hidden js-delete-address" href="javascript:;">Удалить</a> </div> <div class="lk-address-form__input-fields"> <div class="input-text"> <label class="input-text__label" for="address-place">Город</label> <input class="input-text__input" type="text" id="address-place" name="address-place" placeholder=""> </div> <div class="input-text"> <label class="input-text__label" for="address-street">Улица</label> <input class="input-text__input" type="text" id="address-street" name="address-street" placeholder=""> </div> <div class="lk-address-form__input-complex"> <div class="input-text"> <label class="input-text__label" for="address-house">Дом</label> <input class="input-text__input" type="text" id="address-house" name="address-house" placeholder=""> </div> <div class="input-text"> <label class="input-text__label" for="address-building">Корпус</label> <input class="input-text__input" type="text" id="address-building" name="address-building" placeholder=""> </div> <div class="input-text"> <label class="input-text__label" for="address-flat">Квартира</label> <input class="input-text__input" type="text" id="address-flat" name="address-flat" placeholder=""> </div> </div> </div> </div> <div class="lk-address-form__btn-container"> <a class="lk-address-form__save btn btn--colored visually-hidden js-lk-address-save-btn" href="javascript:;">Сохранить</a> <a class="lk-address-form__add btn btn--colored js-lk-address-add-btn" href="javascript:;">Добавить</a> <a class="link link--colored visually-hidden js-lk-add-more-link" href="javascript:;">Добавить ещё</a> </div> </div> </form> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script> <script src="js/script.js"></script> </body> </html> Код:
.visually-hidden { class LkAddressForm { constructor(element, options) { const self = this; self.DATA_KEY = 'lkaddressform'; // опции self.$element = $(element); self.$element.data(self.DATA_KEY, self); self.options = $.extend({}, self.$element.data(), options); //переменные self.$lkNoAddress = self.$element.find('.js-lk-no-address'); self.$lkAddressContainer = self.$element.find('.js-lk-address-container'); self.$lkOneAddress = self.$lkAddressContainer.find('.js-lk-one-address'); self.$lkSaveBtn = self.$lkAddressContainer.find('.js-lk-address-save-btn'); self.$lkAddBtn = self.$lkAddressContainer.find('.js-lk-address-add-btn'); self.$lkAddMoreLink = self.$lkAddressContainer.find('.js-lk-add-more-link'); self.$lkdeleteBtn = self.$lkAddressContainer.find('.js-delete-address'); // функции инициализации self.setListeners(); } setListeners() { const self = this; self.$lkAddBtn.on('click', (e) => { e.preventDefault(); self.addFirstAddress(); }); self.$lkAddMoreLink.on('click', (e) => { e.preventDefault(); self.addMoreAddress(); }); self.$lkdeleteBtn.on('click', (e) => { e.preventDefault(); if (self.$lkAddressContainer.find('.js-lk-one-address').length > 1) { self.deleteOneAddress($(e.currentTarget)); } else { self.deleteLastAddress(); } }); } addFirstAddress() { const self = this; self.$lkOneAddress.removeClass('visually-hidden'); self.$lkNoAddress.addClass('visually-hidden'); self.$lkAddBtn.addClass('visually-hidden'); self.$lkSaveBtn.removeClass('visually-hidden'); self.$lkAddMoreLink.removeClass('visually-hidden'); self.$lkdeleteBtn.removeClass('visually-hidden'); } addMoreAddress() { const self = this; self.$lkOneAddress.clone(true).insertBefore('.lk-address-form__btn-container'); } deleteOneAddress($target) { const self = this; $target.closest('.js-lk-one-address').remove(); } deleteLastAddress() { const self = this; self.$lkOneAddress.addClass('visually-hidden'); self.$lkNoAddress.removeClass('visually-hidden'); self.$lkAddBtn.removeClass('visually-hidden'); self.$lkSaveBtn.addClass('visually-hidden'); self.$lkAddMoreLink.addClass('visually-hidden'); self.$lkdeleteBtn.addClass('visually-hidden'); } } $(() => { $('.js-lk-address-form').each((i, item) => { new LkAddressForm(item); }); }); |
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Document</title> <style> input{ display: block; } div{ margin: 10px 0; } </style> </head> <body> <div class="forms"></div> <button>Добавить</button> <script> var i = 0; j=0; document.querySelector('button').onclick =()=>{ document.querySelector('.forms').insertAdjacentHTML('beforeend', `<div>Форма ${++j} <input type="text" id="id${i++}"/>поле 1 <input type="text" id="id${i++}"/>поле 2 <input type="text" id="id${i++}"/>поле 3 <input type="text" id="id${i++}"/>поле 4 <input type="text" id="id${i++}"/>поле 5 </div>`); }; </script> </body> </html> |
Цитата:
можно тупо добавить копии строк 11 - 18 в строку 72 ... или подумать над логикой ещё. |
Всё же пересмотрел всё и сделал по-другому. Теперь всё работает за одним нюансом: в форме, которая появляется по клику, должна быть по умолчанию checked радиокнопка со значением "Рабочий" http://skrinshoter.ru/s/250718/TyFOJplt?a. Если же кликнуть ещё раз "Добавить ещё", то при появлении второй формы у первой этот checked слетает http://skrinshoter.ru/v/250718/tnU6aud9?a, хотя должен оставаться. Причём эта проблема только при появлении второй формы, дальше - третья, четвёртая и т.д. - добавляются с чекнутой радиокнопкой, как и должно быть. Может, кто-то подскажет, в чём дело и как это исправить? Вот код:
<form class="lk-address-form js-validate js-lk-address-form" action="javascript:;" method="get"> <h2 class="lk-address-form__title">Мои адреса</h2> <p class="lk-address-form__no-address js-lk-address-form-no-address">Вы не добавили еще ни одного адреса.</p> <div class="lk-address-form__container js-lk-address-form-container"> <!--вставляется js-ом--> </div> <div class="lk-address-form__btn-container"> <a class="lk-address-form__save btn btn--colored visually-hidden js-lk-address-submit js-submit" href="javascript:;">Сохранить</a> <a class="lk-address-form__add btn btn--colored js-add-address-btn" href="javascript:;">Добавить <span class="visually-hidden">ещё</span></a> </div> </form> class LkAddressForm { constructor(element, options) { const self = this; self.DATA_KEY = 'lkaddressform'; // опции self.$element = $(element); self.$element.data(self.DATA_KEY, self); self.options = $.extend({}, self.$element.data(), options); //переменные self.$lkAddressContainer = self.$element.find('.js-lk-address-form-container'); self.$lkNoAddress = self.$element.find('.js-lk-address-form-no-address'); self.$lkAddressSubmit = self.$element.find('.js-lk-address-submit'); self.$addAddressBtn = self.$element.find('.js-add-address-btn'); // функции инициализации self.setListeners(); } setListeners() { const self = this; self.$addAddressBtn.on('click', (e) => { self.addAddress(); self.indexingAttributes(['label', 'htmlFor'], ['input', 'name'], ['input', 'id']); self.showHideElems(e); }); self.$lkAddressContainer.on('click', (e) => { if ($(e.target).hasClass('js-delete-address-btn')) { self.deleteAddress(e); self.indexingAttributes(['label', 'htmlFor'], ['input', 'name'], ['input', 'id']); } self.showHideElems(e); }); } //добавляет одну форму с адресом addAddress() { const self = this; self.$lkAddressContainer.append(`<div class="lk-address-form__one-address js-lk-one-address"> <div class="lk-address-form__address-top"> <div class="radio-block"> <span class="radio-block__title">Тип адреса: </span> <div class="radio-block__box"> <div class="input-radio"> <input class="input-radio__input" type="radio" id="work-1" name="address-type-1" checked> <label class="input-radio__label" for="work-1">Рабочий</label> </div> <div class="input-radio"> <input class="input-radio__input" type="radio" id="home-1" name="address-type-1"> <label class="input-radio__label" for="home-1">Домашний</label> </div> </div> </div> <a class="link link--colored js-delete-address-btn" href="javascript:;">Удалить</a> </div> <div class="lk-address-form__input-fields"> <div class="input-text js-parent-input-error"> <label class="input-text__label" for="where-1">Город</label> <input class="input-text__input" type="text" id="where-1" name="where-1" placeholder="" required> <div class="error-message error-message--static"></div> </div> <div class="input-text js-parent-input-error"> <label class="input-text__label" for="street-1">Улица</label> <input class="input-text__input" type="text" id="street-1" name="street-1" placeholder="" required> <div class="error-message error-message--static"></div> </div> <div class="lk-address-form__input-complex"> <div class="input-text js-parent-input-error"> <label class="input-text__label" for="house-1">Дом</label> <input class="input-text__input" type="text" id="house-1" name="house-1" placeholder="" required digits="true"> <div class="error-message error-message--static"></div> </div> <div class="input-text js-parent-input-error"> <label class="input-text__label" for="building-1">Корпус</label> <input class="input-text__input" type="text" id="building-1" name="building-1" placeholder="" digits="true"> <div class="error-message error-message--static"></div> </div> <div class="input-text js-parent-input-error"> <label class="input-text__label" for="flat-1">Квартира</label> <input class="input-text__input" type="text" id="flat-1" name="flat-1" placeholder="" digits="true"> <div class="error-message error-message--static"></div> </div> </div> </div> </div>`); } //удаляет одну форму с адресом deleteAddress(e) { const self = this; $(e.target).closest('.js-lk-one-address').remove(); } //показывает/скрывает фразу "Вы не добавили ещё ни одного адреса", кнопку "Сохранить", видоизменяет кнопку "Добавить" showHideElems(e) { const self = this; if ($(e.target).hasClass('js-add-address-btn') && !self.$lkAddressContainer.find('.js-lk-one-address').length == 0) { self.changeClasses(self.$lkNoAddress, 'visually-hidden'); self.changeClasses(self.$lkAddressSubmit, null, 'visually-hidden'); self.changeClasses($(e.currentTarget), 'link link--colored', 'btn btn--colored'); self.changeClasses(self.$addAddressBtn.find('span'), null, 'visually-hidden'); } if (self.$lkAddressContainer.find('.js-lk-one-address').length == 0) { self.changeClasses(self.$lkNoAddress, null, 'visually-hidden'); self.changeClasses(self.$lkAddressSubmit, 'visually-hidden'); self.changeClasses(self.$addAddressBtn, 'btn btn--colored', 'link link--colored'); self.changeClasses(self.$addAddressBtn.find('span'), 'visually-hidden'); } } //добавляет, удаляет классы у элементов, нужна для работы выше расположенной функции changeClasses(elemToChange, classesToAdd, classesToRemove) { const self = this; if (classesToAdd && !classesToRemove) elemToChange.addClass(classesToAdd); else if (!classesToAdd && classesToRemove) elemToChange.removeClass(classesToRemove); else elemToChange.removeClass(classesToRemove).addClass(classesToAdd); } //пересчитывает значения id, name, for при добавлении/удалении форм, чтобы они всегда начинались с 1 и шли по порядку. indexingAttributes(tagName, tagValue) { const self = this; var addresses = document.getElementsByClassName('js-lk-one-address'); for (var i = 0; i < arguments.length; i++) { var tagName = arguments[i][0], tagValue = arguments[i][1]; for (var j = 0; j < addresses.length; j++) { var tagElems = addresses[j].getElementsByTagName(tagName); var numOfElems = tagElems.length; for (var k = 0; k < numOfElems; k++) { tagElems[k][tagValue] = tagElems[k][tagValue].replace(/\d/, (j + 1).toString()); } } } } } $(() => { $('.js-lk-address-form').each((i, item) => { new LkAddressForm(item); }); }); |
Alessio18911,
name="address-type-1" надо менять в каждой копии на другое |
Рони, спасибо огромное за Ваш быстрый и ценный ответ! Да, теперь дошло, почему так происходило - заменил в шаблоне цифру на "0" и проблема исчезла. Спасибо огромное ещё раз!!!:)
|
Часовой пояс GMT +3, время: 01:47. |