Complex signal graphs, real-time validation, computed form state, and JSON export
// Complex signal graph for form builder
const fields = signal([], 'fields');
const formValues = signal({}, 'formValues');
// Each field's validity depends on its config + current value
const errors = computed(() => {
return fields.value
.filter(f => f.required)
.flatMap(f => validate(f, formValues.value[f.id]));
});
const isValid = computed(() => errors.value.length === 0);
// Signal dependency graph:
// fields ──┬──> errors ──> isValid
// │
// formValues ┘
//
// Changing a field label re-validates.
// Typing in preview re-validates.
// Adding/removing fields re-validates.
// Validate based on field type
function validate(field, value) {
const errs = [];
if (field.required && !value)
errs.push(`${field.label} is required`);
if (field.type === 'email' && value && !value.includes('@'))
errs.push(`${field.label} must be a valid email`);
if (field.type === 'number' && value && isNaN(value))
errs.push(`${field.label} must be a number`);
return errs;
}