Ошибка перенаправления данных динамической HTML-формы AJAX в Google Sheets

#javascript #jquery #ajax

#javascript #jquery #ajax

Вопрос:

Я работаю над отправкой данных формы из динамической формы пользователя на страницу Google Sheets. Существует корпус из 140 потенциальных форм, пользователям случайным образом отображаются 20. Я не получаю никаких ошибок в консоли, но Google Sheet не заполняется. Я знаю, что сценарий sheets gs в порядке, потому что соединение работало нормально в более простых вариантах использования.

Я включил html и js-код, который у меня есть ниже. Веб-сайт отлично отображается на моем локальном компьютере. Изображения и форма также работают.

 <!DOCTYPE html>

<body>
<!-- Required JS packages for this project-->
<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js">
</script>
<script src="jquery-3.3.1.min.js"></script>
<script src="require.js"></script>
    
<!--Create empty form element  -->
<div id = "form_submit"></div>

<!-- JS function to fill form element with 20 hold type questions forms -->
<script>
        // Establish file name to hold mapping with two lists and a dict to link elements
        var files = ['1.png', '10.png', ..., '98.png', '99.png']
        var numWords = ["one", "two", "three",.., "one_hundred_and_fifty"]
        var numWordDict = { 1: 'one', ..., 150: 'one_hundred_and_fifty' }        // Generate list of 20 random digits that will select holds to be classified
       
        // Create array of twenty random holds
        var idx = []
        for (var j = 0; j < 20; j  ) {
            idx.push(Math.floor(Math.random() * 140)   0)
        }
        console.log(idx)

        // Loop over array and make a form element for each hold within the div element
        $(document).ready(function (list) {
            for (var i = 0; i < idx.length; i  ) {
                // retrieve mapped index 
                var randHoldIdx = idx[i]
                // build path to hold image
                var holdPath = files[randHoldIdx]
                var numb = holdPath.match(/d/g);
                numb = numb.join("");
                var colName = numWordDict[numb]
                var form_name = 'submit-to-google-sheet'   numb
                const scriptURL = 'https://script.google.com/macros/s/AKfycbyhMLuTGNkaNOxeNCOx_t1ERThZT8VEYDcMmiQhj773kIrUuRA/exec'

                // Form element contents will be appended into the div element with id = form_submit
                $("#form_submit").append(
                    //  html form skeleton for users to select jug,pinch, crimp, pocket or undercling from radio button
                    //  options
                    "<form name = "   form_name   ">" 
                    "<input type='radio' name = "  colName   " class="   String(colName)  " value=1>Jug<br>"  
                    "<input type='radio' name = "   colName   " class="   String(colName)  " value=2>Pinch<br>"  
                    "<input type='radio'name = "  colName   " class="   String(colName)  " value=3>Crimp<br>" 
                    "<input type='radio' name = "  colName   " class="   String(colName)  " value=4>Pocket<br>" 
                    "<input type='radio' name = "  colName   " class="   String(colName)  " value=5>Undercling" 
                    // Submit button for form, close form
                    "<button type='submit'>Submit!</button></form>" 
                    // image of climbing hold in question with coordinates to position on moonboard
                    "<div><img src=labelled_imgs/"  String(holdPath)  " alt='selected hold'></div>");

                    var form = document.forms[form_name]
    
                    window.onload=function(){
                        form.addEventListener('submit', e => {
                        e.preventDefault()
                        fetch(scriptURL, { method: 'POST', body: new FormData(form) })
                            .then(response => console.log('Success!', response))
                            .catch(error => console.error('Error!', error.message))
        })
    }
                }
            });



    </script>


</body>  

Я подозреваю, что что-то не так с прослушивателем событий. Это может быть что-то простое, но я бы приветствовал любые предложения по альтернативным решениям этой проблемы! Это немного отличается от простой отправки пользовательского ввода из формы в таблицу Google, поскольку содержимое формы изменяется при каждом отображении страницы. Для контекста это часть пользовательской краудсорсинговой платформы. Спасибо за любую помощь!

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

1. Перейдите в редактор сценариев Google Sheets> Просмотр> Выполнение.

2. @TheMaster, после перехода к исполнениям я вижу инициализацию doPost и setup, что мне следует искать здесь?

3. Есть ли какие-либо сбои? Когда- fetch либо попадал в конечную точку? Вы также сказали, что на консоли нет ошибок. Тогда это регистрировалось 'Success!' ?

4. Сообщений о сбоях не поступало, но на консоли также нет сообщения об успешном завершении

5. Развернут ли скрипт так, чтобы любой мог получить доступ, включая анонимный?

Ответ №1:

Проблемы:

  • Вы переписываете window.onload функцию каждый раз в цикле для каждой формы. Только событие отправки последней формы будет отключено onload и отправлено на сервер.

  • Когда вы создаете случайный массив чисел, нет гарантии, что он будет уникальным. Если две формы в конечном итоге имеют одинаковое имя, будет предотвращено только событие отправки первой формы.

Решение:

  • Поскольку форма уже добавлена, непосредственно запустите функцию для каждой формы внутри цикла без записи window.onload

     var form = document.forms[form_name]
    form.addEventListener('submit', e => {
         e.preventDefault();
         fetch(scriptURL, { method: 'POST'.....
      
  • Сделать Idx уникальный:

     idx = [...new Set(idx)]
      

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

1. Это полезно! Вы заметили что-нибудь странное в моем пересмотренном запросе на выборку? Время от времени происходит сбой выборки. Я не уверен, почему.

2. @Max Попробуйте добавить кнопку отправки в конце второго тега скрипта. Для загрузки скрипта требуется время. Таким образом, кнопка отправки добавляется только после предотвращения по умолчанию.

3. хорошая идея, это сгенерировало менее загадочное сообщение об ошибке и отключило перехват ошибки. Сообщение об ошибке «Ошибка при загрузке: POST ‘ script.google.com/macros/s /… «».

4. Интересно, что сообщение терпит неудачу только в Chrome

5. Я обновлял браузер после того, как пользователь нажимал кнопку отправки, которая в некоторых случаях отключала сообщение. Теперь все работает!

Ответ №2:

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

Я опубликовал новый код ниже. Не стесняйтесь обращаться за разъяснениями!

 <!DOCTYPE html>

<body>
  <!-- Required JS packages for this project-->
  <script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.2/jquery.min.js">
  </script>
  <script src="jquery-3.3.1.min.js"></script>
  <script src="require.js"></script>

  <!--Create empty form element  -->
  <div id="form_submit1">
    <form id="form_submit" , name="submit_to_sheets">

    </form>
  </div>

  <!-- JS function to fill form element with 20 hold type questions forms -->
  <script>
    // Establish file name to hold mapping with two lists and a dict to link elements
    var files = ['1.png', '10.png',...,'99.png']
    var numWords = ["one", "two",...,"one_hundred_and_fifty"]
    var numWordDict = {
      1: 'one',
      2: 'two',
      ...
      150: 'one_hundred_and_fifty'
    } // Generate list of 20 random digits that will select holds to be classified

    // Create array of twenty random holds
    var idx = []
    for (var j = 0; j < 20; j  ) {
      idx.push(Math.floor(Math.random() * 140)   0)
    }
    console.log(idx)


    // Loop over array and make a form element for each hold within the div element
    $(document).ready(function(list) {
      for (var i = 0; i < idx.length; i  ) {
        // retrieve mapped index 
        var randHoldIdx = idx[i]
        // build path to hold image
        var holdPath = files[randHoldIdx]
        var numb = holdPath.match(/d/g);
        numb = numb.join("");
        var colName = numWordDict[numb]


        // Form element contents will be appended into the div element with id = form_submit
        $("#form_submit").append(
          //  html form skeleton for users to select jug,pinch, crimp, pocket or undercling from radio button
          //  options
          "<input type='radio' name = "   colName   " class="   String(colName)   " value=1>Jug<br>"  
          "<input type='radio' name = "   colName   " class="   String(colName)   " value=2>Pinch<br>"  
          "<input type='radio'name = "   colName   " class="   String(colName)   " value=3>Crimp<br>"  
          "<input type='radio' name = "   colName   " class="   String(colName)   " value=4>Pocket<br>"  
          "<input type='radio' name = "   colName   " class="   String(colName)   " value=5>Undercling"  

          // image of climbing hold in question with coordinates to position on moonboard
          "<div><img src=labelled_imgs/"   String(holdPath)   " alt='selected hold'></div>");
      }

      // prepend form begining to html outside of for loop
      // append end of form to html outside of for loop


    });
    $("#form_submit").append("<button type='submit'>Submit!</button>");
  </script>

  <script>
    const form = document.forms["submit_to_sheets"]
    const scriptURL = 'https://script.google.com/macros/s/AKfycbyhMLuTGNkaNOxeNCOx_t1ERThZT8VEYDcMmiQhj773kIrUuRA/exec'
    console.log(form)
    console.log("loop")
    form.addEventListener('submit', e => {
      e.preventDefault()
      fetch(scriptURL, {
          method: 'POST',
          body: new FormData(form)
        })
        .then(response => console.log('Success!', response))
        .catch(error => console.error('Error!', error.message))
    })
  </script>


</body>

</html>