dynamic_ui_renderer 0.2.1
dynamic_ui_renderer: ^0.2.1 copied to clipboard
A Flutter package for rendering UI from JSON responses. Build dynamic forms, screens, and components from server-driven JSON.
dynamic_ui_renderer #
A powerful Flutter package for rendering UI dynamically from JSON responses. Build forms, screens, and components from server-driven JSON โ without requiring app updates.
Perfect for: Server-Driven UI (SDUI), Dynamic Forms, A/B Testing, CMS-driven UIs, and White-Label Apps
โจ Features (v0.2.0) #
๐ Complete Forms & Validation System #
- โ Dynamic Form Widget - Full-featured form container with validation
- โ 10+ Field Types - Text, Email, Password, Number, Phone, Dropdown, Checkbox, Date, Textarea, Radio
- โ Real-time Validation - Validate as users type with instant feedback
- โ Multi-Form Support - Handle multiple independent forms with unique IDs
- โ Form Callbacks - Global and per-form submission callbacks with form data
- โ Conditional Visibility - Show/hide fields based on other field values
- โ Form Reset - Complete form reset for all field types
โ 12+ Validation Rules #
| Rule | Description | Example |
|---|---|---|
required |
Field must have a value | {"type": "required"} |
email |
Valid email format | {"type": "email"} |
minLength |
Minimum character length | {"type": "minLength", "value": 8} |
maxLength |
Maximum character length | {"type": "maxLength", "value": 50} |
minValue |
Minimum numeric value | {"type": "minValue", "value": 18} |
maxValue |
Maximum numeric value | {"type": "maxValue", "value": 120} |
pattern |
Regex pattern matching | {"type": "pattern", "pattern": "^[A-Z]+$"} |
match |
Match another field's value | {"type": "match", "value": "password"} |
phone |
Valid phone number format | {"type": "phone"} |
url |
Valid URL format | {"type": "url"} |
date |
Valid date format | {"type": "date"} |
custom |
Custom validation logic | {"type": "custom", "customConfig": {...}} |
๐ฏ Complete Action System #
- โ Print - Debug logging with levels (info/warning/error)
- โ Dialog - Alert dialogs with custom titles and messages
- โ Snackbar - Toast notifications with action buttons
- โ
URL Launch - Open web links in browser (uses
url_launcher) - โ Bottom Sheet - Modal bottom sheets
- โ Navigation - Screen navigation with push/pop strategies
๐จ Core Widgets #
- โ Text - Full styling (size, weight, color, alignment)
- โ Container - Padding, margin, color, dimensions, border radius
- โ Button - Styled buttons with actions
- โ Column - Vertical layouts with alignment
- โ Row - Horizontal layouts with alignment
๐ ๏ธ Developer Experience #
- โ Type-safe JSON parsing - No runtime surprises
- โ Error handling - Graceful fallbacks with user-friendly messages
- โ Context propagation - Automatic for navigation and dialogs
- โ Extensible architecture - Easy to add custom widgets
- โ Well tested - 95%+ code coverage
- โ
Lightweight - Minimal dependencies (
url_launcheronly)
๐ฆ Installation #
Add the dependency to your pubspec.yaml:
dependencies:
dynamic_ui_renderer: ^0.2.0
Then run:
flutter pub get
Note: The package automatically includes
url_launcherfor web URL support. No additional setup needed!
๐ Quick Start #
import 'package:flutter/material.dart';
import 'package:dynamic_ui_renderer/dynamic_ui_renderer.dart';
void main() {
// Register form callbacks (optional)
DynamicUIRenderer.registerFormCallback('login_form', (formId, formData) {
print('Login form submitted: $formData');
});
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({super.key});
@override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: const Text('Dynamic UI Demo')),
body: DynamicUIRenderer.fromJsonString('''
{
"type": "column",
"properties": {
"crossAxisAlignment": "stretch",
"padding": 16
},
"children": [
{
"type": "text",
"properties": {
"text": "Login Form",
"fontSize": 24,
"fontWeight": "bold",
"color": "#2196F3"
}
},
{
"type": "form",
"properties": {
"formId": "login_form",
"submitText": "Login",
"submitButtonColor": "#4CAF50"
},
"fields": [
{
"name": "email",
"type": "email",
"label": "Email",
"required": true,
"validations": [
{"type": "email", "message": "Invalid email"}
]
},
{
"name": "password",
"type": "password",
"label": "Password",
"required": true,
"validations": [
{"type": "minLength", "value": 6}
]
},
{
"name": "rememberMe",
"type": "checkbox",
"label": "Remember me"
}
]
}
]
}
''', context, formId: 'login_form'),
),
);
}
}
๐ Documentation #
๐ Form JSON Schema #
Form Widget
{
"type": "form",
"properties": {
"formId": "unique_form_id", // Optional: for multi-form support
"title": "Form Title", // Optional
"titleFontSize": 18, // Optional
"titleColor": "#1976D2", // Optional
"backgroundColor": "#FFFFFF", // Optional
"padding": 20, // Optional
"borderRadius": 12, // Optional
"elevation": 4, // Optional
"submitText": "Submit", // Optional: default "Submit"
"submitButtonColor": "#4CAF50", // Optional
"submitButtonTextColor": "#FFFFFF", // Optional
"submitButtonRadius": 8, // Optional
"submitButtonHeight": 48, // Optional
"showValidationMessage": true, // Optional: show error snackbar
"validationMessage": "Please fix errors" // Optional: custom error message
},
"fields": [] // Array of field configurations
}
๐ Field Types Reference #
Text Field
{
"name": "username",
"type": "text",
"label": "Username",
"hint": "Enter your username",
"placeholder": "johndoe",
"required": true,
"requiredMessage": "Username is required",
"order": 1,
"validations": [
{"type": "minLength", "value": 3, "message": "Minimum 3 characters"},
{"type": "maxLength", "value": 20, "message": "Maximum 20 characters"}
],
"uiProperties": {
"borderRadius": 8,
"filled": true,
"fillColor": "#F5F5F5",
"fontSize": 16,
"prefixIcon": "person",
"prefixIconColor": "#757575"
}
}
Email Field
{
"name": "email",
"type": "email",
"label": "Email Address",
"hint": "Enter your email",
"required": true,
"validations": [
{"type": "email", "message": "Invalid email format"}
],
"uiProperties": {
"prefixIcon": "email"
}
}
Password Field
{
"name": "password",
"type": "password",
"label": "Password",
"hint": "Create a strong password",
"required": true,
"validations": [
{"type": "minLength", "value": 8, "message": "Minimum 8 characters"},
{"type": "pattern", "pattern": "^(?=.*[A-Za-z])(?=.*\\d).{8,}$",
"message": "Must contain letter and number"}
],
"uiProperties": {
"prefixIcon": "lock"
}
}
Number Field
{
"name": "age",
"type": "number",
"label": "Age",
"hint": "Enter your age",
"validations": [
{"type": "minValue", "value": 18, "message": "Must be 18 or older"},
{"type": "maxValue", "value": 120, "message": "Invalid age"}
]
}
Phone Field
{
"name": "phone",
"type": "phone",
"label": "Phone Number",
"hint": "Enter your phone number",
"validations": [
{"type": "phone", "message": "Invalid phone number"}
],
"uiProperties": {
"prefixIcon": "phone"
}
}
Dropdown Field
{
"name": "country",
"type": "dropdown",
"label": "Country",
"hint": "Select your country",
"required": true,
"options": [
{"label": "United States", "value": "us", "icon": {"name": "home"}},
{"label": "India", "value": "in", "icon": {"name": "home"}},
{"label": "United Kingdom", "value": "uk", "disabled": true}
]
}
Checkbox Field
{
"name": "termsAccepted",
"type": "checkbox",
"label": "I accept the Terms and Conditions",
"required": true,
"requiredMessage": "You must accept the terms",
"uiProperties": {
"activeColor": "#4CAF50",
"checkColor": "#FFFFFF"
}
}
Date Field
{
"name": "birthDate",
"type": "date",
"label": "Birth Date",
"hint": "Select your birth date",
"uiProperties": {
"format": "dd/MM/yyyy",
"iconColor": "#1976D2"
}
}
Textarea Field
{
"name": "message",
"type": "textarea",
"label": "Message",
"hint": "Type your message",
"required": true,
"uiProperties": {
"minLines": 3,
"maxLines": 5
}
}
Radio Field
{
"name": "priority",
"type": "radio",
"label": "Priority",
"options": [
{"label": "Low", "value": "low"},
{"label": "Medium", "value": "medium"},
{"label": "High", "value": "high"}
]
}
๐ฌ Available Action Types #
| Type | Description | Required Parameters | Example |
|---|---|---|---|
print |
Print to console | message, level |
{"message": "Hello", "level": "info"} |
showDialog |
Show alert dialog | title, message, buttonText |
{"title": "Alert", "message": "Hello"} |
showSnackbar |
Show snackbar | message, duration, actionLabel |
{"message": "Saved!", "duration": 3} |
launchUrl |
Open URL in browser | url, mode |
{"url": "https://flutter.dev"} |
showBottomSheet |
Show modal bottom sheet | title, message, buttonText |
{"title": "Options"} |
navigate |
Navigate to route | route, type |
{"route": "/home", "type": "push"} |
๐ฏ Complete Examples #
๐ Multi-Form Demo #
// Register multiple form callbacks
DynamicUIRenderer.registerFormCallback('login_form', (formId, formData) {
print('Login: $formData');
});
DynamicUIRenderer.registerFormCallback('register_form', (formId, formData) {
print('Registration: $formData');
});
// Render forms with different IDs
Column(
children: [
DynamicUIRenderer.fromJsonString(loginFormJson, context, formId: 'login_form'),
DynamicUIRenderer.fromJsonString(registerFormJson, context, formId: 'register_form'),
],
);
๐ Dynamic Layout with Order Property #
{
"type": "form",
"fields": [
{"name": "field1", "type": "text", "label": "Field 1", "order": 3},
{"name": "field2", "type": "text", "label": "Field 2", "order": 1},
{"name": "field3", "type": "text", "label": "Field 3", "order": 2}
]
}
// Fields will render in order: field2, field3, field1
๐ Fetch UI from Server #
Future<Widget> fetchUIFromServer(BuildContext context, String formId) async {
try {
final response = await http.get(
Uri.parse('https://api.example.com/forms/$formId')
);
if (response.statusCode == 200) {
return DynamicUIRenderer.fromJsonString(
response.body,
context,
formId: formId,
);
}
return Text('Error: ${response.statusCode}');
} catch (e) {
return Text('Network error: $e');
}
}
๐ฑ Complete Demo App #
Check out the /example folder for a complete Flutter app demonstrating all features:
cd example
flutter run
The example app includes:
- ๐ฏ Button Actions Demo - Test all 6 action types
- ๐ฑ Core Widgets Demo - Basic widgets showcase
- ๐จ Styling Properties Demo - Colors, fonts, padding, margins
- ๐ Layout Examples Demo - Different alignments and arrangements
- ๐ Multi-Form Demo - Three independent forms with real-time data display
- Registration Form with all field types
- Contact Form with dropdown and textarea
- Dynamic Layout Form with toggleable field order
- โ ๏ธ Error Handling Demo - Graceful fallbacks for unsupported widgets
๐ Architecture Overview #
JSON โ UIComponent (Model) โ WidgetFactory โ Flutter Widget
โ โ
Form Models Properties Parser
โ โ
FormController Action Handler
โ โ
Validation Navigation/Dialogs
The package follows a clean, modular architecture:
- JSON Parsing - Converts JSON to type-safe models
- Form Models - Type-safe field and validation rule definitions
- FormController - Manages form state, validation, and submissions
- Widget Factory - Maps component types to Flutter widgets
- Property Parsers - Safely converts JSON values to Flutter types
- Action Handler - Executes user interactions
๐งช Testing #
# Run all tests
flutter test
# Run with coverage
flutter test --coverage
# Generate coverage report (requires lcov)
genhtml coverage/lcov.info -o coverage/html
# Then open coverage/html/index.html
๐ Package Statistics #
| Metric | Value |
|---|---|
| Latest Version | v0.2.0 |
| Published | February 2026 |
| License | MIT |
| Platforms | Android, iOS, Web, macOS, Linux, Windows |
| Dependencies | url_launcher (automatically included) |
| Field Types | 10+ |
| Validation Rules | 12+ |
| Test Coverage | 95%+ |
๐ค Contributing #
Contributions are welcome! Whether it's:
- ๐ Reporting bugs
- ๐ก Suggesting features
- ๐ Improving documentation
- ๐ง Submitting pull requests
Steps to contribute:
- Fork the repository
- Create your feature branch:
git checkout -b feature/amazing-feature - Commit your changes:
git commit -m "Add some amazing feature" - Push to the branch:
git push origin feature/amazing-feature - Open a Pull Request
๐ License #
This project is licensed under the MIT License - see the LICENSE file for details.
๐ Acknowledgments #
- Inspired by server-driven UI patterns at Airbnb, Lyft, and Prowork
- Built with โค๏ธ for the Flutter community
- Thanks to all contributors and users
๐ Support #
- ๐ง Email: webdevjash6@gmail.com
- ๐ Issues: GitHub Issues
- โญ Star: GitHub Repository
๐ฎ Coming Soon (v0.3.0) #
- ๐ Network Fetching - Load UI directly from URLs
- ๐พ Caching - Cache UI definitions locally
- ๐งฉ Custom Widget Registry - Register your own widgets
- ๐จ Theme Support - Dynamic theming from JSON
- ๐ฆ Plugin System - Easy third-party integrations
If you find this package useful, please consider:
- โญ Starring the GitHub repository
- ๐ข Sharing it with others
- ๐ Reporting issues
- ๐ก Suggesting features
Made for Flutter Community with โค๏ธ by Jashwanth Gowda R