Submit dan Fetch Data Menggunakan SolidJS
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.