Skip to content

Instantly share code, notes, and snippets.

@Kaaveh
Created February 12, 2025 06:12
Show Gist options
  • Save Kaaveh/dbffce449e5d5c15ad0d0c54f15987b8 to your computer and use it in GitHub Desktop.
Save Kaaveh/dbffce449e5d5c15ad0d0c54f15987b8 to your computer and use it in GitHub Desktop.
import 'package:flutter/material.dart';
abstract class FieldRenderer {
Widget render(FormField field);
}
class FieldRendererFactory {
static FieldRenderer? getRenderer(String type) {
switch (type) {
case "input":
return InputFieldRenderer();
case "select":
return SelectFieldRenderer();
case "textarea":
return TextAreaRenderer();
case "text":
return TextRenderer();
default:
return null;
}
}
}
class InputFieldRenderer implements FieldRenderer {
@override
Widget render(FormField field) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: TextField(
decoration: InputDecoration(
hintText: field.props.placeholder ?? "",
),
),
);
}
}
class SelectFieldRenderer implements FieldRenderer {
@override
Widget render(FormField field) {
return Padding(
padding: const EdgeInsets.all(8.0),
child: Column(
crossAxisAlignment: CrossAxisAlignment.start,
children: [
Text(field.label),
DropdownButtonFormField<String>(
value: field.props.options?.first.value ?? "",
items: field.props.options?.map((option) {
return DropdownMenuItem<String>(
value: option.value,
child: Text(option.label),
);
}).toList() ?? [],
onChanged: (value) {},
),
],
),
);
}
}
class TextAreaRenderer implements FieldRenderer {
@override
Widget render(FormField field) {
return Padding(
padding: const EdgeInsets.symmetric(vertical: 8.0),
child: TextField(
decoration: InputDecoration(
labelText: field.label,
hintText: field.props.placeholder ?? "",
),
maxLines: field.props.rows ?? 4,
minLines: 3,
),
);
}
}
class TextRenderer implements FieldRenderer {
@override
Widget render(FormField field) {
return Padding(
padding: EdgeInsets.all(field.style.padding ?? 0),
child: Text(
field.label,
textAlign: _getTextAlign(field.style.alignment),
),
);
}
TextAlign _getTextAlign(String? alignment) {
switch (alignment) {
case "center":
return TextAlign.center;
case "right":
return TextAlign.right;
default:
return TextAlign.start;
}
}
}
class FieldComposer extends StatelessWidget {
final FormModel formModel;
const FieldComposer({
Key? key,
required this.formModel,
}) : super(key: key);
@override
Widget build(BuildContext context) {
return Padding(
padding: const EdgeInsets.all(16.0),
child: Column(
children: formModel.fields.map((field) {
final renderer = FieldRendererFactory.getRenderer(field.type);
return renderer?.render(field) ?? const SizedBox.shrink();
}).toList(),
),
);
}
}
class DynamicScreen extends StatelessWidget {
final FormModel state;
const DynamicScreen({
Key? key,
this.state = const FormModel(),
}) : super(key: key);
@override
Widget build(BuildContext context) {
return FieldComposer(formModel: state);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment