Как динамически добавлять дочерние элементы в форму?
Как сделать так, чтобы при нажатии на кнопку (на скриншотах под номерами) добавлялся дочерний набор элементов в родительский блок с сохранением всей структуры. Более наглядно на скриншотах.

add {
cursor: pointer;
}
input {
font-size: 16px;
width: 170px;
}
input[type=file] {
font-size: 14px;
width: 180px;
}
.block1, .block2, .block3, .block4, .block5, .block6 {
border: solid;
padding: 5px;
margin:5px;
border-width: 2px;
border-color: #000000;
}
.block1 {
width: 340px;
}
.block2 {
width:320px;
}
.block3 {
width:300px;
}
.block4 {
width:280px;
}
.block5 {
width:260px;
}
.block6 {
width:260px;
}
.add1, .add2, .add3, .add4 {
display:inline-block;
cursor: pointer;
padding: 3px;
margin: 3px;
background-color: #e3e3e3;
border-radius: 100%;
font-size: 21px;
width: 26px;
text-align: center;
}
.point, .out, .car, .amount {
display:inline-block;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Форма</title>
</head>
<body>
<div class="form">
<div class="block1">
<input type="text" placeholder="Дата">
<input type="text" placeholder="Вид загрузки">
<div class="block2">
<input type="text" class="out" placeholder="Исходящий">
<div class="add4">4</div>
<div class="block3">
<input type="text" class="point" placeholder="Пункт">
<div class="add3">3</div>
<div class="block4">
<input type="text" class="car" placeholder="ТС">
<div class="add2">2</div>
<div class="block5">
<input type="file" class="amount">
<div class="add1">1</div>
</div>
</div>
</div>
</div>
</div>
<button class="sub-btn">Отправить</button>
</div>
</body>
</html>
Ответы (1 шт):
Автор решения: EzioMercer
→ Ссылка
Можете воспользоваться этим алгоритмом:
const blocks = [
'.block2',
'.block3',
'.block4'
].map(blockQuery => {
const block = document.querySelector(blockQuery).cloneNode(true);
const addBtn = block.querySelector('[class^=add]');
block.removeChild(addBtn);
return block;
});
const amount = document.querySelector('.amount').cloneNode(true);
const addAmount = (e) => {
e.target.parentNode.append(amount.cloneNode(true));
}
const addBlock = (e, index) => {
const block = blocks[index].cloneNode(true);
e.target.parentNode.parentNode.append(block);
}
document.querySelector('.block1').addEventListener('click', (e) => {
switch (e.target.className) {
case 'add1':
addAmount(e);
return;
case 'add2':
addBlock(e, 2);
return;
case 'add3':
addBlock(e, 1);
return;
case 'add4':
addBlock(e, 0);
return;
}
})
add {
cursor: pointer;
}
input {
font-size: 16px;
width: 170px;
}
input[type=file] {
font-size: 14px;
width: 180px;
}
.block1,
.block2,
.block3,
.block4,
.block5,
.block6 {
border: solid;
padding: 5px;
margin: 5px;
border-width: 2px;
border-color: #000000;
}
.block1 {
width: 340px;
}
.block2 {
width: 320px;
}
.block3 {
width: 300px;
}
.block4 {
width: 280px;
}
.block5 {
width: 260px;
}
.block6 {
width: 260px;
}
.add1,
.add2,
.add3,
.add4 {
display: inline-block;
cursor: pointer;
padding: 3px;
margin: 3px;
background-color: #e3e3e3;
border-radius: 100%;
font-size: 21px;
width: 26px;
text-align: center;
}
.point,
.out,
.car,
.amount {
display: inline-block;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Форма</title>
</head>
<body>
<div class="form">
<div class="block1">
<input type="text" placeholder="Дата">
<input type="text" placeholder="Вид загрузки">
<div class="block2">
<input type="text" class="out" placeholder="Исходящий">
<div class="add4">4</div>
<div class="block3">
<input type="text" class="point" placeholder="Пункт">
<div class="add3">3</div>
<div class="block4">
<input type="text" class="car" placeholder="ТС">
<div class="add2">2</div>
<div class="block5">
<input type="file" class="amount">
<div class="add1">1</div>
</div>
</div>
</div>
</div>
</div>
<button class="sub-btn">Отправить</button>
</div>
</body>
</html>
UPD
Если немного изменить дизайн добавления после нажатия на 1, то код можно сократить ещё больше и это даже будет быстрее работать:
const blocks = [
'.block2',
'.block3',
'.block4',
'.block5'
].map(blockQuery => {
const block = document.querySelector(blockQuery).cloneNode(true);
const addBtn = block.querySelector('[class^=add]');
block.removeChild(addBtn);
return block;
});
const addBlock = (parentBlock, originalBlock) => {
const block = originalBlock?.cloneNode(true);
parentBlock.append(block || '');
}
const classToBlock = {
add1: blocks[3],
add2: blocks[2],
add3: blocks[1],
add4: blocks[0],
};
document.querySelector('.block1').addEventListener('click', (e) => {
addBlock(e.target.parentNode.parentNode, classToBlock[e.target.className]);
})
add {
cursor: pointer;
}
input {
font-size: 16px;
width: 170px;
}
input[type=file] {
font-size: 14px;
width: 180px;
}
.block1,
.block2,
.block3,
.block4,
.block5,
.block6 {
border: solid;
padding: 5px;
margin: 5px;
border-width: 2px;
border-color: #000000;
}
.block1 {
width: 340px;
}
.block2 {
width: 320px;
}
.block3 {
width: 300px;
}
.block4 {
width: 280px;
}
.block5 {
width: 260px;
}
.block6 {
width: 260px;
}
.add1,
.add2,
.add3,
.add4 {
display: inline-block;
cursor: pointer;
padding: 3px;
margin: 3px;
background-color: #e3e3e3;
border-radius: 100%;
font-size: 21px;
width: 26px;
text-align: center;
}
.point,
.out,
.car,
.amount {
display: inline-block;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>Форма</title>
</head>
<body>
<div class="form">
<div class="block1">
<input type="text" placeholder="Дата">
<input type="text" placeholder="Вид загрузки">
<div class="block2">
<input type="text" class="out" placeholder="Исходящий">
<div class="add4">4</div>
<div class="block3">
<input type="text" class="point" placeholder="Пункт">
<div class="add3">3</div>
<div class="block4">
<input type="text" class="car" placeholder="ТС">
<div class="add2">2</div>
<div class="block5">
<input type="file" class="amount">
<div class="add1">1</div>
</div>
</div>
</div>
</div>
</div>
<button class="sub-btn">Отправить</button>
</div>
</body>
</html>



