Submit dan Fetch Data Menggunakan SolidJS

mrfdn author

Rafi

Cara submit dan fetch data dari dan ke Google Sheet dengan menggunakan komponen Solidjs di Astro JS untuk digunakan sebagai kolom ucapan web invitation.

mrfdn.com - Kali ini saya sedang belajar Solidjs.

Di sini saya ingin submit dan fetch data secara otomatis dari dan ke google sheet.

Saya menggunakan Astro, dan menjalankan SolidJS sebagai component.

Komponen ini yang saya buat ini digunakan untuk menghandle kirim ucapan / komentar untuk web invitation.

Di sini saya dibantu oleh ChatGPT untuk generate codingan solid js.

Langsung saja begini caranya:

Daftar Isi

Install package solidjs

Pastikan sudah install solid di projekan astro

npx astro add solid

settingan tambahan astro akan otomatis regenerate di file astro.config.mjs

Folder structure

sekarang kita hanya perlu bekerja di file berikut:

src/
├── pages
│   ├── index.astro
└── solid
    ├── app.jsx
    └── form.jsx

Componen solid disimpan pada foler /src/solid/.

Buat komponen utama SolidJS : App.jsx

// App.jsx
import { createSignal, onCleanup } from 'solid-js';
import KonfirmasiHadir from './form.jsx';

// Define the URL of the CSV endpoint
const csvEndpoint = "https://docs.google.com/spreadsheets/d/asdfasdfadsfak/export?format=csv";

// SolidJS component
function App() {
  // State to hold the JSON data
  const [jsonData, setJsonData] = createSignal(null);

  // Function to fetch CSV data and convert it to JSON
  async function fetchAndConvert() {
    try {
      // Make an HTTP request to the CSV endpoint using the built-in fetch function
      const response = await fetch(csvEndpoint);

      // Check if the request was successful (status code 200)
      if (!response.ok) {
        throw new Error(`HTTP error! Status: ${response.status}`);
      }

      // Get the CSV data as text
      const csvData = await response.text();

      // Parse CSV text directly (replace with your own CSV parsing logic)
      const jsonArray = parseCsvText(csvData);

      // Process the resulting JSON array
      console.log(jsonArray);

      // Update the component state with the JSON data
      setJsonData(jsonArray);
    } catch (error) {
      console.error('Error fetching or converting data:', error.message);
    }
  }

  // Callback function to be passed to KonfirmasiHadir component
  const handleDataSubmitted = () => {
    // Fetch data in App component when form is submitted
    fetchAndConvert();
  };

  // Function to parse CSV text into a JSON array
  function parseCsvText(csvText) {
    // Replace this logic with your own CSV parsing implementation
    const lines = csvText.split('\n');
    const headers = lines[0].split(',');
    const jsonArray = [];

    for (let i = 1; i < lines.length; i++) {
      const values = lines[i].split(',');
      const entry = {};

      for (let j = 0; j < headers.length; j++) {
        entry[headers[j]] = values[j];
      }

      jsonArray.push(entry);
    }

    return jsonArray;
  }

  // Fetch data when the component mounts
  fetchAndConvert();

  // Cleanup function to cancel any ongoing fetch when the component unmounts
  onCleanup(() => {
    // Any cleanup logic, e.g., cancelling ongoing requests
  });

  // Render the component
  return (
    <div>
      {jsonData() ? (
        // Render your JSON data as needed
        <>
      <KonfirmasiHadir onDataSubmitted={handleDataSubmitted} />
          <ul style="padding:0;">
            {jsonData().map((item, index) => (
              <li style="list-style:none;" key={index}>
               <p style="font-weight:bold;">{item.nama}</p>
               <i>{item.pesan}</i>
                <hr/>
              </li>
            ))}
          </ul>
        </>
      ) : (
        // Render a loading indicator or other UI while fetching data
        <p>Loading...</p>
      )}
    </div>
  );
}

export default App;

Buat komponen Form.jsx

import { createSignal } from 'solid-js';

function KonfirmasiHadir({ onDataSubmitted }) {
  const [hadirChecked, setHadirChecked] = createSignal(false);
  const [loading, setLoading] = createSignal(false);
  const [formSubmitted, setFormSubmitted] = createSignal(false);

  const scriptURL = 'https://script.google.com/macros/s/asdfasdgasdfagasdf/exec';

  const handleSubmit = async (event) => {
    event.preventDefault();

    setLoading(true);

    try {
      const form = event.target;
      const formData = new FormData(form);

      const response = await fetch(scriptURL, { method: 'POST', body: formData });

      if (response.ok) {
        console.log('Success!', response);
        setFormSubmitted(true);

        // Reset the form
        form.reset();

        // Trigger the callback function
        if (onDataSubmitted) {
          onDataSubmitted();
        }
      } else {
        console.error('Error!', response.statusText);
      }
    } catch (error) {
      console.error('Error!', error.message);
    } finally {
      setLoading(false);
    }
  };

  const handleHadirChange = () => {
    setHadirChecked(!hadirChecked());
  };

  return (
    <form class="" name="submit-form" onSubmit={handleSubmit}  >

      <label class="">
        Nama lengkap
        <input
          name="nama"
          type="text"
          class=""
          required
        />
      </label>

      <div class="my-6">
        <label for="hadir" class="">
          <input
            type="radio"
            id="hadir"
            name="konfirmasi"
            value="yes"
            checked={hadirChecked()}
            onChange={handleHadirChange}
            class="text-black"
            required
          />
          Ya, saya akan datang
        </label>

        <label for="tidakhadir" class="block font-bold">
          <input
            type="radio"
            id="tidakhadir"
            name="konfirmasi"
            value="no"
            checked={!hadirChecked()}
            onChange={handleHadirChange}
            class="text-black"
            required
          />
          Tidak, saya tidak bisa datang
        </label>
      </div>

      <div id="hadirberapa" style={{ display: hadirChecked() ? "block" : "none" }} class="block font-bold">
        <label for="floatingPassword" class="block font-bold">
          Berapa orang?
          <input
            type="text"
            inputmode="numeric"
            pattern="[0-9]+"
            name="jumlah"
            class=""
          />
        </label>
      </div>

      <div class="">
        <label for="ucapan" class="block font-bold">
          Isi ucapan
          <input
            name="pesan"
            type="text"
            class=""
          />
        </label>
      </div>

      <button class={`bg-blue-400 ${loading() ? "hidden" : "block"} bg-white/20 p-4 font-bold`} type="submit" disabled={loading()}>
        Kirim
      </button>
      <button class={`bg-red-400 ${loading() ? "" : "hidden"} bg-white/20 p-4 font-bold`}>Loading</button>



    {/*<button
        type="submit"
        class="bg-blue-500 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded"
        disabled={loading()}
      >
        {loading() ? 'Loading...' : 'Kirim'}
      </button>

      {formSubmitted() && (
      <p class="text-green-500 font-bold mt-4">Terima kasih, data Anda telah terkirim!</p>
      )}*/}
    </form>
  );
}

export default KonfirmasiHadir;

Panggil komponennya di halaman astro: index.astro

---
import App from "../solid/app.jsx";
---
<html lang="en">
	<head>
		<meta charset="utf-8" />
		<link rel="icon" type="image/svg+xml" href="/favicon.svg" />
		<meta name="viewport" content="width=device-width" />
		<meta name="generator" content={Astro.generator} />
		<title>Komentar</title>
	</head>
	<body>
		<App client:load />
	</body>
</html>

Jangan lupa set client:load supaya astro bisa load fungsi pada komponen tersebut.

Kesimpulan

Jadi pada form ini, setelah menekan tombol kirim, maka akan mengirim data dulu ke google sheet kemudian secara otomatis komponen utama (App.jsx) akan fetch data lagi dari google sheet.

Semoga bermanfaat.

mrfdn author

Rafi

  • 15 year+ of Linux user.
  • 5 years+ blogger and web developer.

Jika artikel yang dibuatnya ternyata bermanfaat, support dengan cara

Baca juga