У меня есть форма в листах Google, куда я отправляю динамические данные с листа.
Я зацикливаю данные листа и создаю такое же количество блоков в форме, как и количество моих заголовков.
У меня есть первый блок элементов, написанный на html. Остальные блоки клонирую из первого, клонирую его ID и отправляю свои заголовки листов на элементы формы.
Первый заголовок, который я пишу (с последним заголовком из массива) в единственный блок, существующий перед циклом.
Затем я клонирую этот блок, давая клону новые заголовки и пытаясь вставить клоны перед первым блоком ([0]), но получается неправильно и перезаписывает мой первый жестко заданный заголовок.
Он добавляет блоки в случайном порядке, поэтому я не могу получить свои заголовки в правильной последовательности, например «1,2,3». Это всегда как "2,1,1" или "1,3,2" и т.д.
Я пробовал разные варианты добавления клонированных элементов (например, motherDiv.appendChild(clonedRow) и motherDiv.insertBefore(clonedRow, motherDiv.children[0]), но не могу заставить их работать должным образом.
Пожалуйста, укажите, что здесь не так.
Вот код и скрин:
//my google app backend function with data
var numbers = [1, 2, 3]
var stats = ["Валовый доход", "Кол-во клиентов", "Кол-во размещенной рекламы"]
var stats = {
statNumbers: numbers,
statStats: stats
}
//select initialization
document.addEventListener('DOMContentLoaded', function() {
var getstats = getStats();
var elems = document.querySelectorAll('select');
var instances = M.FormSelect.init(elems);
});
//getting stats object
function getStats() {
google.script.run.withSuccessHandler(processStats).statsObj();
google.script.run.withFailureHandler(showError).statsObj()
return;
}
//creating dynamic stats fields in the form
function processStats(stats) {
//name first statistic with the last number
var firstStat = document.getElementById("statName").innerHTML = stats.statNumbers[stats.statStats.length - 1] + ". " + stats.statStats[stats.statStats.length - 1]
//mother div
var motherDiv = document.getElementById("motherDiv")
//sample row to copy
var statRow = document.getElementById("statsample");
//loop stat names
for (var i = 0; i < stats.statStats.length - 1; i++) {
var statName = stats.statStats[i]
var statNumber = stats.statNumbers[i]
//cloning the original row
var clonedRow = statRow.cloneNode(true)
//setting unique ID to whole row
var rowId = clonedRow.id = "statsample" + i
//setting unique ID to stat div
var clonedStatID = motherDiv.getElementsByClassName("statClass")[0].id = "statName" + statNumber
//stat titles (except first one)
var statHtml = document.getElementById(clonedStatID).innerHTML = statNumber + ". " + statName;
var err = document.getElementById("err").innerHTML = motherDiv.children.length
//appending it to the mother div
//motherDiv.appendChild(clonedRow);
motherDiv.insertBefore(clonedRow, motherDiv.children[0]);
}
return;
}
function showError() {
var err = document.getElementById("err").innerHTML = "There was an error."
}<!--Import Google Icon Font-->
<link href = "https://fonts.googleapis.com/icon?family=Material+Icons" rel = "stylesheet">
<!-- Compiled and minified CSS -->
<link rel = "stylesheet" href = "https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<div id = "motherDiv">
<!-- mother div -->
<div class = "row" id = "statsample">
<div class = " input-field col s3 #fffde7 yellow lighten-5">
<h6 id = "statName" class = "statClass"></h6>
</div>
<div class = "input-field col s3">
<select class = "icons browser-default" id = "weeksSel4">
<option value = "" disabled selected>Неделя</option>
</select>
</div>
<div class = "input-field col s2">
<input id = "numbers" type = "text" class = "validate">
<label for = "numbers">Значение</label>
</div>
<div class = "input-field col s1.5">
<select class = "icons browser-default" id = "measure">
<option value = "" disabled selected>Ед. изм:</option>
<option value = "">шт.</option>
<option value = "">%</option>
<option value = "">$</option>
<option value = "">руб.</option>
<option value = "">грн.</option>
</select>
</div>
<div class = "input-field col s2.5">
<a class = "waves-effect waves-light btn-small #039be5 light-blue darken-1" style = "float: right;" id = "btn1row"><i class = "material-icons right">send</i>Ввести</a>
</div>
</div>
<!-- row end -->
</div>
<!-- mother div end-->
<div id = "err"> </div>Я пробовал оба направления: начиная с первого и т. д. и начиная с последнего и добавляя раньше: во всех вариантах, которые я пробовал, он добавляет строки в таком случайном порядке, и я никогда не получаю 1, 2, 3.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Я бы рекомендовал заполнить «главный» div первым элементом массива, а для клонов начать итерацию по массиву с индекса 1.
Нам нужно внести некоторые фундаментальные изменения в вашу функцию processStats(stats).
Сначала заполните мастер:
var firstStat = document.getElementById("statName").innerHTML = stats.statNumbers[0] + ". " + stats.statStats[0];
следующие две строки остаются нетронутыми
var motherDiv = document.getElementById("motherDiv")
var statRow = document.getElementById("statsample");
Измените цикл for, чтобы он начинался с 1
for (var i = 1; i < stats.statStats.length; i++) {
}
Теперь сам цикл for нуждается в некоторых изменениях. Эти три строки в порядке
var statName = stats.statStats[i];
var statNumber = stats.statNumbers[i];
var clonedRow = statRow.cloneNode(true);
Я не понимаю следующее
var clonedStatID = motherDiv.getElementsByClassName("statClass")[0].id = "statName" + statNumber
Я знаю, что вы хотите дать только что клонированному дочернему элементу div статкласс уникальный идентификатор с порядковым номером, но с каждой итерацией цикла for это будет давать идентификатор первому элементу в списке. Выше у вас уже есть переменная, которая содержит ссылку на клонированный div клонированная строка, который вы также можете использовать для доступа к его дочерним элементам.
Так что избавьтесь от строки и используйте это:
clonedRow.getElementsByTagName("h6")[0].innerHTML = statNumber + ". " + statName;
Теперь просто добавьте div к родителю
motherDiv.appendChild(clonedRow);
Вот рабочий пример — просто нажмите «Выполнить фрагмент кода», чтобы увидеть его в действии:
//my google app backend function with data
var numbers = [1, 2, 3]
var stats = ["Валовый доход", "Кол-во клиентов", "Кол-во размещенной рекламы"]
var stats = {
statNumbers: numbers,
statStats: stats
}
function processStats(stats) {
//name first statistic with the last number
var firstStat = document.getElementById("statName").innerHTML = stats.statNumbers[0] + ". " + stats.statStats[0];
//mother div
var motherDiv = document.getElementById("motherDiv")
//sample row to copy
var statRow = document.getElementById("statsample");
//loop stat names
for (var i = 1; i < stats.statStats.length; i++) {
var statName = stats.statStats[i];
var statNumber = stats.statNumbers[i];
var clonedRow = statRow.cloneNode(true);
var rowId = clonedRow.id = "statsample" + i;
clonedRow.getElementsByTagName("h6")[0].innerHTML = statNumber + ". " + statName;
var err = document.getElementById("err").innerHTML = motherDiv.children.length
motherDiv.appendChild(clonedRow);
}
return;
}
function showError() {
var err = document.getElementById("err").innerHTML = "There was an error."
}
processStats(stats);<!--Import Google Icon Font-->
<link href = "https://fonts.googleapis.com/icon?family=Material+Icons" rel = "stylesheet">
<!-- Compiled and minified CSS -->
<link rel = "stylesheet" href = "https://cdnjs.cloudflare.com/ajax/libs/materialize/1.0.0/css/materialize.min.css">
<div id = "motherDiv">
<!-- mother div -->
<div class = "row" id = "statsample">
<div class = " input-field col s3 #fffde7 yellow lighten-5">
<h6 id = "statName" class = "statClass"></h6>
</div>
<div class = "input-field col s3">
<select class = "icons browser-default" id = "weeksSel4">
<option value = "" disabled selected>Неделя</option>
</select>
</div>
<div class = "input-field col s2">
<input id = "numbers" type = "text" class = "validate">
<label for = "numbers">Значение</label>
</div>
<div class = "input-field col s1.5">
<select class = "icons browser-default" id = "measure">
<option value = "" disabled selected>Ед. изм:</option>
<option value = "">шт.</option>
<option value = "">%</option>
<option value = "">$</option>
<option value = "">руб.</option>
<option value = "">грн.</option>
</select>
</div>
<div class = "input-field col s2.5">
<a class = "waves-effect waves-light btn-small #039be5 light-blue darken-1" style = "float: right;" id = "btn1row"><i class = "material-icons right">send</i>Ввести</a>
</div>
</div>
<!-- row end -->
</div>
<!-- mother div end-->
<div id = "err"> </div>Это потрясающе, спасибо! Я вижу свою ошибку сейчас. Вы полностью помогли мне в этом! Теперь все работает исправно.
Нет проблем, Кики, рад, что смог помочь!
Верно) не могли бы вы помочь и с этим? Я добавил туда комментарии с новыми данными stackoverflow.com/questions/56798076/…
Почему именно вы заполняете «главный» div статистика значениями из последнего элемента внутри массива и пытаетесь добавить клоны раньше? Я бы сказал, просто дайте мастеру данные из первого элемента массива, а остальные клонируйте.