JsonInputFieldAppi
A specialized input widget for editing and validating JSON data with syntax highlighting and interactive editing capabilities.
Overview
JsonInputFieldAppi
provides a powerful interface for JSON data input and editing. It combines a text field trigger with a full-screen JSON editor dialog, offering syntax highlighting, validation, and support for both object and string data modes.
Features
- 📝 Interactive JSON Editor - Full-screen editing with syntax highlighting
- 🎨 Syntax Highlighting - Color-coded JSON elements for better readability
- ✅ Built-in Validation - Automatic JSON validation and error handling
- 📱 Modal Interface - Clean dialog-based editing experience
- 🔄 Dual Mode Support - Object editing and raw string editing
- 🎯 Form Integration - Seamless integration with Flutter forms
- 🌈 Custom Theming - Customizable color schemes and styling
- 💾 State Management - Automatic state preservation and validation
Basic Usage
JsonInputFieldAppi(
widgetKey: GlobalKey<FormFieldState<String>>(),
formKey: GlobalKey<FormState>(),
lable: 'Configuration',
hint: 'Enter JSON configuration',
title: 'Edit Configuration',
mandatory: true,
onChanged: (jsonData) {
print('JSON Data: $jsonData');
},
)
Properties
Property | Type | Default | Description |
---|---|---|---|
widgetKey | GlobalKey<FormFieldState<String>> | required | Form field key for validation |
formKey | GlobalKey<FormState> | required | Form key for form management |
lable | String? | null | Label text for the input field |
hint | String? | null | Hint text for the input field |
title | String? | null | Title for the JSON editor dialog |
mandatory | bool? | false | Whether the field is required |
onChanged | Function(Map<String, dynamic>)? | null | Callback for JSON object changes |
onChangedString | Function(String)? | null | Callback for string data changes |
initialValue | Map<String, dynamic>? | null | Initial JSON object value |
initialString | String? | null | Initial string value (for string mode) |
suffixIcon | Widget? | null | Custom suffix icon for the trigger field |
preffixIcon | Widget? | null | Custom prefix icon for the trigger field |
stringData | bool? | false | Enable string editing mode instead of object mode |
textStyle | TextStyle? | null | Text style for the trigger field |
Examples
Basic JSON Object Editor
class JsonFormExample extends StatefulWidget {
_JsonFormExampleState createState() => _JsonFormExampleState();
}
class _JsonFormExampleState extends State<JsonFormExample> {
final _formKey = GlobalKey<FormState>();
final _jsonFieldKey = GlobalKey<FormFieldState<String>>();
Map<String, dynamic> configData = {};
Widget build(BuildContext context) {
return Form(
key: _formKey,
child: Column(
children: [
JsonInputFieldAppi(
widgetKey: _jsonFieldKey,
formKey: _formKey,
lable: 'Application Configuration',
hint: 'Click to edit JSON configuration',
title: 'Edit App Configuration',
mandatory: true,
initialValue: {
'theme': 'dark',
'language': 'en',
'features': ['notifications', 'analytics']
},
onChanged: (jsonData) {
setState(() {
configData = jsonData;
});
},
),
ElevatedButton(
onPressed: () {
if (_formKey.currentState!.validate()) {
print('Valid JSON: $configData');
}
},
child: Text('Save Configuration'),
),
],
),
);
}
}
String Mode Editor
JsonInputFieldAppi(
widgetKey: GlobalKey<FormFieldState<String>>(),
formKey: GlobalKey<FormState>(),
lable: 'Raw JSON Data',
hint: 'Enter raw JSON string',
title: 'Edit JSON String',
stringData: true, // Enable string mode
initialString: '{"key": "value"}',
onChangedString: (jsonString) {
print('JSON String: $jsonString');
// Parse and validate if needed
try {
final parsed = json.decode(jsonString);
print('Parsed successfully: $parsed');
} catch (e) {
print('Invalid JSON: $e');
}
},
)
With Custom Styling
JsonInputFieldAppi(
widgetKey: _fieldKey,
formKey: _formKey,
lable: 'API Response',
hint: 'Configure API response format',
title: 'API Response Editor',
textStyle: TextStyle(
fontSize: 16,
fontWeight: FontWeight.w500,
),
suffixIcon: Icon(
Icons.code,
color: Colors.blue,
),
preffixIcon: Icon(
Icons.settings,
color: Colors.grey,
),
onChanged: (data) {
handleApiConfigChange(data);
},
)
Complex JSON Structure
JsonInputFieldAppi(
widgetKey: _complexFieldKey,
formKey: _formKey,
lable: 'Database Schema',
hint: 'Define database schema',
title: 'Database Schema Editor',
mandatory: true,
initialValue: {
'tables': {
'users': {
'columns': {
'id': {'type': 'integer', 'primary': true},
'name': {'type': 'string', 'required': true},
'email': {'type': 'string', 'unique': true}
}
},
'posts': {
'columns': {
'id': {'type': 'integer', 'primary': true},
'title': {'type': 'string', 'required': true},
'content': {'type': 'text'},
'user_id': {'type': 'integer', 'foreign_key': 'users.id'}
}
}
}
},
onChanged: (schema) {
validateAndSaveSchema(schema);
},
)
JSON Editor Features
Syntax Highlighting
The JSON editor provides color-coded syntax highlighting:
- Keys: White text for object keys
- Strings: Orange text for string values
- Numbers: Red text for numeric values
- Booleans: Purple text for true/false values
- Brackets: Blue text for structural elements
- Comments: Grey text for comments (if supported)
- Errors: Red highlighting for syntax errors
Theme Customization
The editor uses a dark theme optimized for JSON editing:
JsonEditorThemeData(
lightTheme: JsonTheme(
defaultStyle: TextStyle(
color: Colors.yellow,
fontSize: 20,
fontWeight: FontWeight.w600,
),
bracketStyle: TextStyle(color: Colors.blue, fontSize: 20),
numberStyle: TextStyle(color: Colors.red),
stringStyle: TextStyle(color: Colors.orange),
boolStyle: TextStyle(color: Colors.purple),
keyStyle: TextStyle(color: Colors.white),
commentStyle: TextStyle(color: Colors.grey),
errorStyle: TextStyle(color: Colors.red),
),
)
Validation
Automatic Validation
The widget automatically validates JSON structure and provides feedback:
JsonInputFieldAppi(
// ... other properties
mandatory: true,
onChanged: (data) {
// Validation happens automatically
// Invalid JSON will trigger form validation errors
},
)
Custom Validation
Implement additional validation logic:
bool validateJsonStructure(Map<String, dynamic> data) {
// Custom validation logic
if (!data.containsKey('required_field')) {
return false;
}
if (data['version'] == null || data['version'] < 1.0) {
return false;
}
return true;
}
JsonInputFieldAppi(
// ... other properties
onChanged: (data) {
if (validateJsonStructure(data)) {
// Valid structure
saveConfiguration(data);
} else {
// Show error message
showErrorDialog('Invalid JSON structure');
}
},
)
Integration Patterns
With State Management
// Using Provider
class ConfigProvider extends ChangeNotifier {
Map<String, dynamic> _config = {};
Map<String, dynamic> get config => _config;
void updateConfig(Map<String, dynamic> newConfig) {
_config = newConfig;
notifyListeners();
}
}
// In your widget
Consumer<ConfigProvider>(
builder: (context, provider, child) {
return JsonInputFieldAppi(
initialValue: provider.config,
onChanged: (data) {
provider.updateConfig(data);
},
// ... other properties
);
},
)
With API Integration
class ApiConfigWidget extends StatefulWidget {
_ApiConfigWidgetState createState() => _ApiConfigWidgetState();
}
class _ApiConfigWidgetState extends State<ApiConfigWidget> {
Map<String, dynamic> apiConfig = {};
bool isLoading = false;
Future<void> saveConfig() async {
setState(() => isLoading = true);
try {
await ApiService.updateConfiguration(apiConfig);
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Configuration saved successfully')),
);
} catch (e) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Error saving configuration: $e')),
);
} finally {
setState(() => isLoading = false);
}
}
Widget build(BuildContext context) {
return Column(
children: [
JsonInputFieldAppi(
widgetKey: GlobalKey<FormFieldState<String>>(),
formKey: GlobalKey<FormState>(),
lable: 'API Configuration',
title: 'Edit API Settings',
onChanged: (data) {
setState(() {
apiConfig = data;
});
},
),
SizedBox(height: 16),
ElevatedButton(
onPressed: isLoading ? null : saveConfig,
child: isLoading
? CircularProgressIndicator()
: Text('Save Configuration'),
),
],
);
}
}
Best Practices
- Validation: Always implement proper validation for critical JSON data
- Error Handling: Provide clear error messages for invalid JSON
- Performance: For large JSON objects, consider implementing lazy loading
- User Experience: Use meaningful titles and labels for the editor dialog
- Data Backup: Consider implementing auto-save or draft functionality
- Security: Validate and sanitize JSON data before processing
Common Use Cases
- Configuration Management: App settings and configuration files
- API Testing: Request/response body editing
- Data Import/Export: Structured data manipulation
- Schema Definition: Database or API schema configuration
- Template Editing: JSON-based template systems
- Metadata Management: File or content metadata editing
Related Widgets
- TextFieldAppi - For basic text input
- SearchableTextFieldAppi - For searchable selections
- QuillEditorAppi - For rich text editing
Migration Notes
When upgrading from basic text fields:
- Replace text controllers with form keys for proper validation
- Update callbacks to handle Map<String, dynamic> instead of strings
- Implement proper error handling for JSON parsing
- Consider using string mode for backward compatibility
Ready for rich text editing? Check out QuillEditorAppi for advanced text formatting capabilities!