javascripthtmlgoogle-sheetsgoogle-apps-scriptpostman

Error submitting data: Failed to fetch, while submitting html css, js form data to google sheets


step1.html

    <!doctype html>
<html lang="en">
<head>
    <meta charset="utf-8">
    <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
    <title>Visa Points Calculator</title>
    <link rel="stylesheet" href="bootstrap.css">
    <link rel="stylesheet" href="bootstrap.min.css">
    <link rel="stylesheet" href="style.css">
</head>
<body class="bg-light">
    <div class="container py-5">
        <div class="text-center">
            <h1>Visa Points Calculator Step-1</h1>
        </div>
        
        <form id="visaForm">
            <div class="row">
            <div class="col-md-6">
            <div class="form-group">
                <label for="candidateName">Candidate's Name:</label>
                <input type="text" class="form-control" id="candidateName" required>
            </div>

            <div class="form-group">
                <label for="contactNumber">Contact Number:</label>
                <input type="tel" class="form-control" id="contactNumber" required>
            </div>

            <div class="form-group">
                <label for="dob">Date of Birth:</label>
                <input type="date" class="form-control" id="dob" required>
            </div>

            <div class="form-group">
                <label for="email">Email ID:</label>
                <input type="email" class="form-control" id="email" required>
            </div>

            <div class="form-group">
                <label>Highest Education:</label><br>
                <input type="radio" name="education" value="10th"> 10th<br>
                <input type="radio" name="education" value="12th"> 12th<br>
                <input type="radio" name="education" value="Graduate"> Graduate<br>
                <input type="radio" name="education" value="Postgraduate"> Postgraduate<br>
                <input type="radio" name="education" value="Doctorate"> Doctorate<br>
            </div>

            <div class="form-group">
                <label for="degree">Educational Degrees:</label>
                <input type="text" class="form-control" id="degree">
            </div>

            <div class="form-group">
                <label>Assets:</label><br>
                <input type="checkbox" value="Irrigation Land"> Irrigation Land<br>
                <input type="checkbox" value="Commercial Land"> Commercial Land<br>
                <input type="checkbox" value="Apartment or Flat"> Apartment or Flat<br>
                <input type="checkbox" value="House"> House<br>
            </div>
            </div>

            <div class="col-md-6">
            <div class="form-group">
                <label for="currentVisaCountry">Current Visa Country(If any):</label>
                <select class="form-control" id="currentVisaCountry">
                    
                </select>
            </div>

            <div class="form-group">
                <label for="newVisaCountry">Want a visa to:</label>
                <select class="form-control" id="newVisaCountry">
                    
                </select>
            </div>

            <div class="form-group">
                <label for="visaRejectionCountries">Visa Rejection Countries(If any):</label>
                <select class="form-control" id="visaRejectionCountries">
                    
                </select>
            </div>

            <div class="form-group">
                <label for="lastVisaRejectionDate">Last Visa Rejection Date(If any):</label>
                <input type="date" class="form-control" id="dob" required>
            </div>

            <div class="form-group">
                <label>Profession:</label><br>
                <input type="radio" name="profession" value="Student" onclick="toggleIncomeFields(false)"> Student<br>
                <input type="radio" name="profession" value="Businessman" onclick="toggleIncomeFields(true)"> Businessman<br>
                <input type="radio" name="profession" value="Salaried" onclick="toggleIncomeFields(true)"> Salaried Employee<br>
            </div>

            <div id="incomeFields" style="display: none;">
                <div class="form-group">
                    <label for="monthlyIncome">Monthly Income(In Indian Rupees):</label>
                    <input type="text" class="form-control" id="monthlyIncome">
                </div>
                <div class="form-group">
                    <label>Income Type:</label><br>
                    <input type="checkbox" value="Business"> Business<br>
                    <input type="checkbox" value="Salaried"> Salaried<br>
                    <input type="checkbox" value="Other"> Other<br>
                </div>
            </div>

            </div>
            </div>

            <div style="text-align: center;">
                <button type="submit" class="btn btn-primary">Step-2</button>
            </div>
        </form>
    </div>

    <script>
        const countries = ["None", "Afghanistan", "Albania", "Algeria", "Andorra", "Angola", "Argentina", "Australia", "Austria", "Bangladesh", "Belgium", "Brazil", "Canada", "China", "Denmark", "Egypt", "Finland", "France", "Germany", "India", "Italy", "Japan", "Mexico", "Netherlands", "Norway", "Pakistan", "Russia", "Saudi Arabia", "South Africa", "Spain", "Sweden", "Switzerland", "United Kingdom", "United States"];
        
        function populateCountries(selectId) {
            const selectElement = document.getElementById(selectId);
            countries.forEach(country => {
                const option = document.createElement('option');
                option.value = country;
                option.textContent = country;
                selectElement.appendChild(option);
            });
        }

        populateCountries('currentVisaCountry');
        populateCountries('newVisaCountry');
        populateCountries('visaRejectionCountries');

        function toggleIncomeFields(show) {
            document.getElementById('incomeFields').style.display = show ? 'block' : 'none';
        }


        function toggleIncomeFields(show) {
            document.getElementById('incomeFields').style.display = show ? 'block' : 'none';
        }

        document.getElementById('visaForm').addEventListener('submit', function(e) {
    e.preventDefault();

    const formData = new FormData(e.target);
    let data = {};

    // Convert FormData to JSON Object
    formData.forEach((value, key) => {
        if (data[key]) {
            if (Array.isArray(data[key])) {
                data[key].push(value);
            } else {
                data[key] = [data[key], value];
            }
        } else {
            data[key] = value;
        }
    });

    // Collect checked checkboxes manually
    data['assets'] = Array.from(document.querySelectorAll('input[type="checkbox"]:checked')).map(cb => cb.value);

    fetch('https://script.google.com/macros/s/AKfycbxOF8FLSlEd1sVmineXKQtph2Ix1RokQcJ3VuCYR3veLyi7xo98h3eW0zTvQN_fFnNK/exec', {
        method: 'POST',
         mode: 'cors',  // Ensure CORS mode is enabled
        body: JSON.stringify(data),
        headers: { 'Content-Type': 'application/json' }
    })
    .then(response => {
        if (!response.ok) {
            throw new Error(`HTTP error! Status: ${response.status}`);
        }
        return response.json();
    })
    .then(responseJson => {
        if (responseJson.result === "success") {
            alert('Data submitted successfully');
            window.location.href = '/stepcountries.html';
        } else {
            alert('Error in Google Apps Script: ' + JSON.stringify(responseJson));
        }
    })
    .catch(error => alert('Error submitting data: ' + error.message));
});

    </script>
</body>
</html>

Google sheet App Script:

    function doPost(e) {
  try {
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
    const data = JSON.parse(e.postData.contents);

    const values = [
      data['candidateName'],
      data['contactNumber'],
      data['dob'],
      data['email'],
      data['education'],
      JSON.stringify(data['assets']),  // Convert assets to JSON
      data['currentVisaCountry'],
      data['newVisaCountry'],
      data['visaRejectionCountries'],
      data['degree'],
      data['profession'],
      data['monthlyIncome']
    ];

    sheet.appendRow(values);

    // ✅ Return a response with proper CORS headers
    return ContentService.createTextOutput(JSON.stringify({ result: 'success' }))
      .setMimeType(ContentService.MimeType.JSON);
      
  } catch (error) {
    return ContentService.createTextOutput(JSON.stringify({ result: 'error', message: error.message }))
      .setMimeType(ContentService.MimeType.JSON);
  }
}

// ✅ Handle CORS Preflight Requests (OPTIONS)
function doGet(e) {
  return ContentService.createTextOutput("")
    .setMimeType(ContentService.MimeType.TEXT)
}

PostMan shows no error on handling and submitting data into sheets.

Error faced in browser when interacting live website link:https://ashrithmanagementservicelimited.github.io/VisaScore/step1.html

Error in dev mode:

    `Access to fetch at 'https://script.google.com/macros/s/AKfycbzbAyTfLqI3rJJJd2aYy6XdYZD60wViYYkwxzwSSyuc-i7zrW79t4J0gjdHF2olYdy0/exec'
 from origin 'https://ashrithmanagementservicelimited.github.io' has been blocked
 by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.
 If an opaque response serves your needs, set the request's mode to 'no-cors' to fetch the resource with CORS disabled.Understand this errorAI
    step1.html:167 

        
        
       POST https://script.google.com/macros/s/AKfycbzbAyTfLqI3rJJJd2aYy6XdYZD60wViYYkwxzwSSyuc-i7zrW79t4J0gjdHF2olYdy0/exec net::ERR_FAILED`

Another Google Sheet App Script:

    function doPost(e) {
  try {
    const sheet = SpreadsheetApp.getActiveSpreadsheet().getSheetByName('Sheet1');
    const data = JSON.parse(e.postData.contents);

    const values = [
      data['candidateName'],
      data['contactNumber'],
      data['dob'],
      data['email'],
      data['education'],
      JSON.stringify(data['assets']),  // Convert assets to JSON
      data['currentVisaCountry'],
      data['newVisaCountry'],
      data['visaRejectionCountries'],
      data['degree'],
      data['profession'],
      data['monthlyIncome']
    ];

    sheet.appendRow(values);

    // ✅ Return a response with proper CORS headers
    return ContentService.createTextOutput(JSON.stringify({ result: 'success' }))
      .setMimeType(ContentService.MimeType.JSON)
      .setHeader("Access-Control-Allow-Origin", "*")
      .setHeader("Access-Control-Allow-Methods", "POST, GET")
      .setHeader("Access-Control-Allow-Headers", "Content-Type: application/json")

      
  } catch (error) {
    return ContentService.createTextOutput(JSON.stringify({ result: 'error', message: error.message }))
      .setMimeType(ContentService.MimeType.JSON)
      .setHeader("Access-Control-Allow-Origin", "*")
      .setHeader("Access-Control-Allow-Methods", "POST, GET")
      .setHeader("Access-Control-Allow-Headers", "Content-Type: application/json")

  }
}

// ✅ Handle CORS Preflight Requests (OPTIONS)
function doGet(e) {
  return ContentService.createTextOutput("")
    .setMimeType(ContentService.MimeType.JSON)
    .setHeader("Access-Control-Allow-Origin", "*")
    .setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS")
    .setHeader("Access-Control-Allow-Headers", "Content-Type: application/json")

}

Error while executing Script:

TypeError: ContentService.createTextOutput(...).setMimeType(...).setHeader is not a function
doPost  @ Code.gs:34

Another script:

return HtmlService.createHtmlOutput(JSON.stringify({ result: 'error', message: error.message }))
      .setMimeType(ContentService.MimeType.JSON)
      .setXFrameOptionsMode(HtmlService.XFrameOptionsMode.ALLOWALL);
  }

Same browser error appears as above but postman displays no error and saves data


Solution

  • In your script, in order to remove your current issue, how about the following modification?

    From:

    fetch('https://script.google.com/macros/s/AKfycbxOF8FLSlEd1sVmineXKQtph2Ix1RokQcJ3VuCYR3veLyi7xo98h3eW0zTvQN_fFnNK/exec', {
        method: 'POST',
         mode: 'cors',  // Ensure CORS mode is enabled
        body: JSON.stringify(data),
        headers: { 'Content-Type': 'application/json' }
    })
    

    To:

    fetch('https://script.google.com/macros/s/AKfycbxOF8FLSlEd1sVmineXKQtph2Ix1RokQcJ3VuCYR3veLyi7xo98h3eW0zTvQN_fFnNK/exec', {
        method: 'POST',
        body: JSON.stringify(data),
    })
    

    Note:

    Reference: