Interactive Form Components
This demo showcases how to combine multiple LemonadeJS plugins to create rich, reactive user interfaces with real-time two-way data binding. Build beautiful forms with color pickers, star ratings, toggle switches, and modal dialogs.
<html>
<script src="https://cdn.jsdelivr.net/npm/lemonadejs/dist/lemonade.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@lemonadejs/rating/dist/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@lemonadejs/switch/dist/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@lemonadejs/modal/dist/index.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/@jsuites/color-picker/dist/index.min.js"></script>
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lemonadejs/rating/dist/style.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lemonadejs/switch/dist/style.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@lemonadejs/modal/dist/style.min.css" />
<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/@jsuites/color-picker/dist/style.min.css" />
<div id="root"></div>
<script>
function InteractiveFormDemo() {
const self = this;
// Form data as direct properties
self.name = '';
self.favoriteColor = '#3498db';
self.rating = 0;
self.notifications = true;
self.darkMode = false;
self.emailUpdates = true;
// Handler functions for components
self.updateRating = function(el, value) {
self.rating = value;
self.refresh();
};
self.updateNotifications = function(el, value) {
self.notifications = value;
};
self.updateDarkMode = function(el, value) {
self.darkMode = value;
};
self.updateEmailUpdates = function(el, value) {
self.emailUpdates = value;
};
// Show modal with summary
self.showSummary = function() {
const summary = `
Name: ${self.name || 'Not provided'}
Favorite Color: ${self.favoriteColor}
Rating: ${self.rating} stars
Notifications: ${self.notifications ? 'Enabled' : 'Disabled'}
Dark Mode: ${self.darkMode ? 'On' : 'Off'}
Email Updates: ${self.emailUpdates ? 'Subscribed' : 'Unsubscribed'}
`;
alert(summary);
}
return `<div style="max-width: 900px; margin: 0 auto; padding: 20px;">
<h3 style="text-align: center; margin-bottom: 30px;">User Preferences Form</h3>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 30px;">
<div style="background: white; padding: 20px; border-radius: 8px; border: 1px solid #e0e0e0;">
<label style="display: block; margin-bottom: 8px; font-weight: 600;">Name:</label>
<input type="text" :bind="self.name"
style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;" />
</div>
<div style="background: white; padding: 20px; border-radius: 8px; border: 1px solid #e0e0e0;">
<label style="display: block; margin-bottom: 8px; font-weight: 600;">Favorite Color:</label>
<div style="display: flex; align-items: center; gap: 10px;">
<input type="color" :bind="self.favoriteColor"
style="width: 60px; height: 40px; border: none; cursor: pointer;" />
<span style="font-family: monospace;">{{self.favoriteColor}}</span>
</div>
</div>
<div style="background: white; padding: 20px; border-radius: 8px; border: 1px solid #e0e0e0;">
<label style="display: block; margin-bottom: 8px; font-weight: 600;">Rate Your Experience:</label>
<Rating :value="self.rating" :onchange="self.updateRating" />
</div>
<div style="background: white; padding: 20px; border-radius: 8px; border: 1px solid #e0e0e0;">
<label style="display: block; margin-bottom: 12px; font-weight: 600;">Preferences:</label>
<div style="display: flex; flex-direction: column; gap: 12px;">
<label style="display: flex; align-items: center; cursor: pointer;">
<Switch :value="self.notifications" :onchange="self.updateNotifications" />
<span style="margin-left: 10px;">Enable Notifications</span>
</label>
<label style="display: flex; align-items: center; cursor: pointer;">
<Switch :value="self.darkMode" :onchange="self.updateDarkMode" />
<span style="margin-left: 10px;">Dark Mode</span>
</label>
<label style="display: flex; align-items: center; cursor: pointer;">
<Switch :value="self.emailUpdates" :onchange="self.updateEmailUpdates" />
<span style="margin-left: 10px;">Email Updates</span>
</label>
</div>
</div>
</div>
<button onclick="self.showSummary()"
style="padding: 10px 20px; background: #3498db; color: white;
border: none; border-radius: 4px; cursor: pointer; font-size: 16px; display: block; margin: 0 auto;">
Show Summary
</button>
<div style="margin-top: 30px; padding: 15px; background: #f8f9fa;
border-radius: 4px; border: 1px solid #e9ecef;">
<h4>Live Data Preview:</h4>
<pre style="background: white; padding: 10px; border-radius: 4px;
overflow-x: auto;">{{JSON.stringify({
name: self.name,
favoriteColor: self.favoriteColor,
rating: self.rating,
notifications: self.notifications,
darkMode: self.darkMode,
emailUpdates: self.emailUpdates
}, null, 2)}}</pre>
</div>
</div>`;
}
lemonade.render(InteractiveFormDemo, document.getElementById('root'));
</script>
</html>
import lemonade from 'lemonadejs';
import Rating from '@lemonadejs/rating';
import Switch from '@lemonadejs/switch';
export default function InteractiveFormDemo() {
const self = this;
// Form data as direct properties
self.name = '';
self.favoriteColor = '#3498db';
self.rating = 0;
self.notifications = true;
self.darkMode = false;
self.emailUpdates = true;
// Handler functions for components
self.updateRating = function(el, value) {
self.rating = value;
self.refresh();
};
self.updateNotifications = function(el, value) {
self.notifications = value;
};
self.updateDarkMode = function(el, value) {
self.darkMode = value;
};
self.updateEmailUpdates = function(el, value) {
self.emailUpdates = value;
};
// Show modal with summary
self.showSummary = function() {
const summary = `
Name: ${self.name || 'Not provided'}
Favorite Color: ${self.favoriteColor}
Rating: ${self.rating} stars
Notifications: ${self.notifications ? 'Enabled' : 'Disabled'}
Dark Mode: ${self.darkMode ? 'On' : 'Off'}
Email Updates: ${self.emailUpdates ? 'Subscribed' : 'Unsubscribed'}
`;
alert(summary);
}
return `<div style="max-width: 900px; margin: 0 auto; padding: 20px;">
<h3 style="text-align: center; margin-bottom: 30px;">User Preferences Form</h3>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 30px;">
<div style="background: white; padding: 20px; border-radius: 8px; border: 1px solid #e0e0e0;">
<label style="display: block; margin-bottom: 8px; font-weight: 600;">Name:</label>
<input type="text" :bind="self.name"
style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;" />
</div>
<div style="background: white; padding: 20px; border-radius: 8px; border: 1px solid #e0e0e0;">
<label style="display: block; margin-bottom: 8px; font-weight: 600;">Favorite Color:</label>
<div style="display: flex; align-items: center; gap: 10px;">
<input type="color" :bind="self.favoriteColor"
style="width: 60px; height: 40px; border: none; cursor: pointer;" />
<span style="font-family: monospace;">{{self.favoriteColor}}</span>
</div>
</div>
<div style="background: white; padding: 20px; border-radius: 8px; border: 1px solid #e0e0e0;">
<label style="display: block; margin-bottom: 8px; font-weight: 600;">Rate Your Experience:</label>
<Rating :value="self.rating" :onchange="self.updateRating" />
</div>
<div style="background: white; padding: 20px; border-radius: 8px; border: 1px solid #e0e0e0;">
<label style="display: block; margin-bottom: 12px; font-weight: 600;">Preferences:</label>
<div style="display: flex; flex-direction: column; gap: 12px;">
<label style="display: flex; align-items: center; cursor: pointer;">
<Switch :value="self.notifications" :onchange="self.updateNotifications" />
<span style="margin-left: 10px;">Enable Notifications</span>
</label>
<label style="display: flex; align-items: center; cursor: pointer;">
<Switch :value="self.darkMode" :onchange="self.updateDarkMode" />
<span style="margin-left: 10px;">Dark Mode</span>
</label>
<label style="display: flex; align-items: center; cursor: pointer;">
<Switch :value="self.emailUpdates" :onchange="self.updateEmailUpdates" />
<span style="margin-left: 10px;">Email Updates</span>
</label>
</div>
</div>
</div>
<button onclick="self.showSummary()"
style="padding: 10px 20px; background: #3498db; color: white;
border: none; border-radius: 4px; cursor: pointer; font-size: 16px; display: block; margin: 0 auto;">
Show Summary
</button>
<div style="margin-top: 30px; padding: 15px; background: #f8f9fa;
border-radius: 4px; border: 1px solid #e9ecef;">
<h4>Live Data Preview:</h4>
<pre style="background: white; padding: 10px; border-radius: 4px;
overflow-x: auto;">{{JSON.stringify({
name: self.name,
favoriteColor: self.favoriteColor,
rating: self.rating,
notifications: self.notifications,
darkMode: self.darkMode,
emailUpdates: self.emailUpdates
}, null, 2)}}</pre>
</div>
</div>`;
}
import React, { useState } from 'react';
import { Rating } from '@lemonadejs/rating/react';
import { Switch } from '@lemonadejs/switch/react';
import '@lemonadejs/rating/dist/style.min.css';
import '@lemonadejs/switch/dist/style.min.css';
export default function InteractiveFormDemo() {
const [userData, setUserData] = useState({
name: '',
favoriteColor: '#3498db',
rating: 0,
notifications: true,
darkMode: false,
emailUpdates: true
});
const updateField = (field, value) => {
setUserData(prev => ({ ...prev, [field]: value }));
};
const showSummary = () => {
const summary = `
Name: ${userData.name || 'Not provided'}
Favorite Color: ${userData.favoriteColor}
Rating: ${userData.rating} stars
Notifications: ${userData.notifications ? 'Enabled' : 'Disabled'}
Dark Mode: ${userData.darkMode ? 'On' : 'Off'}
Email Updates: ${userData.emailUpdates ? 'Subscribed' : 'Unsubscribed'}
`;
alert(summary);
};
return (
<div style={{ maxWidth: '900px', margin: '0 auto', padding: '20px' }}>
<h3 style={{ textAlign: 'center', marginBottom: '30px' }}>User Preferences Form</h3>
<div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '20px', marginBottom: '30px' }}>
<div style={{ background: 'white', padding: '20px', borderRadius: '8px', border: '1px solid #e0e0e0' }}>
<label style={{ display: 'block', marginBottom: '8px', fontWeight: '600' }}>Name:</label>
<input
type="text"
value={userData.name}
onChange={(e) => updateField('name', e.target.value)}
style={{ width: '100%', padding: '8px', border: '1px solid #ddd', borderRadius: '4px' }}
/>
</div>
<div style={{ background: 'white', padding: '20px', borderRadius: '8px', border: '1px solid #e0e0e0' }}>
<label style={{ display: 'block', marginBottom: '8px', fontWeight: '600' }}>Favorite Color:</label>
<div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
<input
type="color"
value={userData.favoriteColor}
onChange={(e) => updateField('favoriteColor', e.target.value)}
style={{ width: '60px', height: '40px', border: 'none', cursor: 'pointer' }}
/>
<span style={{ fontFamily: 'monospace' }}>{userData.favoriteColor}</span>
</div>
</div>
<div style={{ background: 'white', padding: '20px', borderRadius: '8px', border: '1px solid #e0e0e0' }}>
<label style={{ display: 'block', marginBottom: '8px', fontWeight: '600' }}>Rate Your Experience:</label>
<Rating
value={userData.rating}
onchange={(value) => updateField('rating', value)}
/>
<span style={{ marginLeft: '10px' }}>{userData.rating} / 5 stars</span>
</div>
<div style={{ background: 'white', padding: '20px', borderRadius: '8px', border: '1px solid #e0e0e0' }}>
<label style={{ display: 'block', marginBottom: '12px', fontWeight: '600' }}>Preferences:</label>
<div style={{ display: 'flex', flexDirection: 'column', gap: '12px' }}>
<label style={{ display: 'flex', alignItems: 'center', cursor: 'pointer' }}>
<Switch
value={userData.notifications}
onchange={(value) => updateField('notifications', value)}
/>
<span style={{ marginLeft: '10px' }}>Enable Notifications</span>
</label>
<label style={{ display: 'flex', alignItems: 'center', cursor: 'pointer' }}>
<Switch
value={userData.darkMode}
onchange={(value) => updateField('darkMode', value)}
/>
<span style={{ marginLeft: '10px' }}>Dark Mode</span>
</label>
<label style={{ display: 'flex', alignItems: 'center', cursor: 'pointer' }}>
<Switch
value={userData.emailUpdates}
onchange={(value) => updateField('emailUpdates', value)}
/>
<span style={{ marginLeft: '10px' }}>Email Updates</span>
</label>
</div>
</div>
</div>
<button
onClick={showSummary}
style={{
padding: '10px 20px',
background: '#3498db',
color: 'white',
border: 'none',
borderRadius: '4px',
cursor: 'pointer',
fontSize: '16px',
display: 'block',
margin: '0 auto'
}}
>
Show Summary
</button>
<div style={{
marginTop: '30px',
padding: '15px',
background: '#f8f9fa',
borderRadius: '4px',
border: '1px solid #e9ecef'
}}>
<h4>Live Data Preview:</h4>
<pre style={{
background: 'white',
padding: '10px',
borderRadius: '4px',
overflowX: 'auto'
}}>
{JSON.stringify(userData, null, 2)}
</pre>
</div>
</div>
);
}
<template>
<div style="max-width: 900px; margin: 0 auto; padding: 20px;">
<h3 style="text-align: center; margin-bottom: 30px;">User Preferences Form</h3>
<div style="display: grid; grid-template-columns: 1fr 1fr; gap: 20px; margin-bottom: 30px;">
<div style="background: white; padding: 20px; border-radius: 8px; border: 1px solid #e0e0e0;">
<label style="display: block; margin-bottom: 8px; font-weight: 600;">Name:</label>
<input
type="text"
v-model="userData.name"
style="width: 100%; padding: 8px; border: 1px solid #ddd; border-radius: 4px;"
/>
</div>
<div style="background: white; padding: 20px; border-radius: 8px; border: 1px solid #e0e0e0;">
<label style="display: block; margin-bottom: 8px; font-weight: 600;">Favorite Color:</label>
<div style="display: flex; align-items: center; gap: 10px;">
<input
type="color"
v-model="userData.favoriteColor"
style="width: 60px; height: 40px; border: none; cursor: pointer;"
/>
<span style="font-family: monospace;">{{ userData.favoriteColor }}</span>
</div>
</div>
<div style="background: white; padding: 20px; border-radius: 8px; border: 1px solid #e0e0e0;">
<label style="display: block; margin-bottom: 8px; font-weight: 600;">Rate Your Experience:</label>
<Rating v-model="userData.rating" />
<span style="margin-left: 10px;">{{ userData.rating }} / 5 stars</span>
</div>
<div style="background: white; padding: 20px; border-radius: 8px; border: 1px solid #e0e0e0;">
<label style="display: block; margin-bottom: 12px; font-weight: 600;">Preferences:</label>
<div style="display: flex; flex-direction: column; gap: 12px;">
<label style="display: flex; align-items: center; cursor: pointer;">
<Switch v-model="userData.notifications" />
<span style="margin-left: 10px;">Enable Notifications</span>
</label>
<label style="display: flex; align-items: center; cursor: pointer;">
<Switch v-model="userData.darkMode" />
<span style="margin-left: 10px;">Dark Mode</span>
</label>
<label style="display: flex; align-items: center; cursor: pointer;">
<Switch v-model="userData.emailUpdates" />
<span style="margin-left: 10px;">Email Updates</span>
</label>
</div>
</div>
</div>
<button
@click="showSummary"
style="padding: 10px 20px; background: #3498db; color: white;
border: none; border-radius: 4px; cursor: pointer; font-size: 16px; display: block; margin: 0 auto;"
>
Show Summary
</button>
<div style="margin-top: 30px; padding: 15px; background: #f8f9fa;
border-radius: 4px; border: 1px solid #e9ecef;">
<h4>Live Data Preview:</h4>
<pre style="background: white; padding: 10px; border-radius: 4px; overflow-x: auto;">{{ JSON.stringify(userData, null, 2) }}</pre>
</div>
</div>
</template>
<script>
import { Rating } from '@lemonadejs/rating/vue';
import { Switch } from '@lemonadejs/switch/vue';
import '@lemonadejs/rating/dist/style.min.css';
import '@lemonadejs/switch/dist/style.min.css';
export default {
name: 'InteractiveFormDemo',
components: {
Rating,
Switch
},
data() {
return {
userData: {
name: '',
favoriteColor: '#3498db',
rating: 0,
notifications: true,
darkMode: false,
emailUpdates: true
}
}
},
methods: {
showSummary() {
const summary = `
Name: ${this.userData.name || 'Not provided'}
Favorite Color: ${this.userData.favoriteColor}
Rating: ${this.userData.rating} stars
Notifications: ${this.userData.notifications ? 'Enabled' : 'Disabled'}
Dark Mode: ${this.userData.darkMode ? 'On' : 'Off'}
Email Updates: ${this.userData.emailUpdates ? 'Subscribed' : 'Unsubscribed'}
`;
alert(summary);
}
}
}
</script>