Search code examples
javascriptgoogle-apps-scriptgoogle-sheetsgoogle-apps

Google App Script Closure error when calling script


This is my first foray into Google scripts and I have a form that calls two different Google app scripts(both are in the .gs file). One Uploads a file while the other saves the form data to a google spreadsheet. For some reason I get an error when calling the file upload script

(Uncaught TypeError: Cannot read property 'closure_lm_407634' of null)

While the script that uploads the data works fine. Saving the form data to spreadsheet(which works):

google.script.run.withUserObject(data).saveToSheet(data);

-- which calls:

function saveToSheet(data) {
  var date = new Date();
  var sheet = SpreadsheetApp.openById(submissionSSKey);
  sheet
    .appendRow([date, data.name, data.email, data.headline,
      data.location, data.newsContent, data.websiteContent, data.expiry, data.fileUrl]); 
}

Uploading file(doesn't work):

google.script.run
  .withUserObject(theForm)
  .withSuccessHandler(processForm)
  .uploadFile(theForm);

-- which calls:

function uploadFile(form) {
  var folder = DriveApp.getFolderById(folderId), doc = '', file = form.uploadedFile;
  if (file.getName()) { doc = folder.createFile(file); }
  return doc;
}

I can't for the life of me figure out why one call works while the other does not. I've tried every way I could think of to call the upload script but nothing works. I've tried removing the user object and success handler.

HTML:

<?!= include('styles'); ?>
<div id="container" class="col-lg-12 col-md-12 col-sm-12">
    <header class="col-lg-offset-3 col-md-offset-3"></header>
    <div class="col-lg-offset-3 col-lg-6 col-md-6 col-sm-12" id="form">
        <h1 class="text-center">
            SAS News Submission
        </h1>
        <span id="required-content">
            <sup>*</sup>
            Required
        </span>
        <br>
        <br>
        <form name="sas-form">
            <label for="name" class="required">Contact Person/ Source of News</label>
            <input type="text" name="name" value="test" class="form-control" id="name" required="required">
            <br>
            <label for="email" class="required">Contact Person's email (in case we have questions regarding your News content)</label>
            <input type="email" name="email" value="[email protected]" id="email" class="form-control" required="required">
            <br>

            <label for="headline" class="required">Headline (try to keep below 10 words if possible) </label>
            <input type="text" name="headline" value="headline" id="headline" class="form-control" required="required">
            <br>

            <label for="newsContent" class="required">News Content *Note all content must be fully edited to ensure posting</label>
                <textarea rows="5" cols="0" name="newsContent" class="form-control" id="newsContent" required="required">
                         Content
                </textarea>
            <br>

            <label class="required">Where would you like the News to be shared? (You may choose more than one)</label>
            <ul id="social-list">
                <li>
                    <input type="checkbox" name="newsletter" id="newsletter" value="newsletter">
                    <label for="newsletter"> Newsletter</label>
                </li>
                <li>
                    <input type="checkbox" name="social" id="social" value="social">
                    <label for="social"> Social Media (Facebook, LinkedIn, Twitter)</label>
                </li>
                <li>
                    <input type="checkbox" name="website" id="website" value="website" checked>
                    <label for="website"> Website </label>
                </li>
            </ul>
            <br>

            <label for="websiteContent">If you chose the website, please provide specific instructions on where you would like the content to be posted.</label>
            <br>
            <small>News and Events Page, Volunteer Page, Student Page, etc. Ex: Please post in the News and Events Page and send the link and headline out on social media.</small>
            <textarea rows="5" cols="0" name="websiteContent" id="websiteContent" class="form-control">website content</textarea>
            <br>
            <label for="expiry">If your content has an expiration date, please share that date below.</label>
            <input type="date" name="expiry" id="expiry" class="form-control">
            <br>
            <label>If you have files that need to be attached, pick them below.</label>
            <input type="file" name="uploadedFile" id="file">
            <br>
            <div id="not-valid"><span></span></div>
            <div id="error"><span>
              An error occurred, please try submitting again.
            </span></div>
            <div id="success"><span>
             Form submission was successful!  Thank you!
            </span></div>
            <input type="button" value="Submit" class="btn btn-primary" id="submit"
                   onclick="validateForm(this.parentNode)">
        </form>
    </div>
</div>
<footer>
<?!= include('javascript'); ?>
</footer>
<script>
    var validateForm = function(theForm)
    {
       var valid = true;
       $('#not-valid span').empty();
       $('input').removeClass('warning');

       if($('#name').val() == '')
       {
             $('#name').addClass('warning');
             $('#not-valid span').append('Please enter a name <br>');
             valid = false;
       }

       if($('#email').val() == '')
       {
             $('#email').addClass('warning');
             $('#not-valid span').append('Please enter an email <br>');
              valid = false;
       }

       if($('#headline').val() == '')
       {
           $('#headline').addClass('warning');
           $('#not-valid span').append('Please enter a headline <br>');
           valid = false;
       }

       if($('#newsContent').val() == '')
       {
           $('#newsContent').addClass('warning');
           $('#not-valid span').append('Please enter news content <br>');
           valid = false;
       }

       if(!$('#social').is(':checked') && !$('#website').is(':checked') && !$('#newsletter').is(':checked'))
       {
          $('#not-valid span').append('Please choose where you would like the news to be shared. <br>');
          $('#social-list').addClass('warning');
          valid = false;
       }


        if(valid)
        {
            google.script.run.withSuccessHandler(processForm).uploadFile(theForm)

        }
    };

    function processForm(file)
    {
        var fileUrl = file ? file.getUrl() : 'No file uploaded',
        location    = [];

        if($('#social').is(':checked'))
        {
            location.push('social');
        }

        if($('#newsletter').is(':checked'))
        {
            location.push('newletter');
        }

        if($('#website').is(':checked'))
        {
            location.push('website');
        }

        var data = {
        name:           $('#name').val(),
        email:          $('#email').val(),
        headline:       $('#headline').val(),
        location:       location.toString(),
        newsContent:    $('#newsContent').val(),
        websiteContent: $('#websiteContent').val(),
        expiry:         $('#expiry').val() ? $('#expiry').val()  : 'No expiration date selected',
        fileUrl:        fileUrl
        };

        google.script.run.saveToSheet(data);         

        clearForm();
        success();
    };

    var clearForm = function()
    {
      $("input[type=text], input[type=date], textarea, input[type=email], input[type=file]").val("");
      $("input[type=checkbox]").attr('checked', false);
      enableSubmit();
    };

    var success = function()
    {
      $('#success').show()
    };

    var enableSubmit = function()
    {
       $("#submit").prop('disabled', false);
    };
</script>

Solution

  • I was able to reproduce your error. I have no idea why that error is occurring, but I found a way to make it work.

    Here is what you need to do:

    Put an id attribute into the upper form tag:

    <form id="myForm">
    
    • Remove the button using an input tag.
    • Add a <button> tag outside of the form. Must be outside of the form. And get the form with document.getElementById('myForm')

      <form id="myForm">
        <input type="file" name="uploadedFile"> 
      </form>
      
      <button onclick="validateForm(document.getElementById('myForm'))">submit</button>
      

    I've tested this. It got the file, and sent it to the server inside of the form element.

    You can use Logger.log() in the server code without using the debugger.

    function uploadFile(form) {
      Logger.log('form: ' + form);
      Logger.log('form.uploadedFile: ' + form.uploadedFile);
      Logger.log('form.uploadedFile: ' + form.uploadedFile.getName());