SDUI
SDUI make it easy to implement Server Driven UI pattern on flutter.
- The server decides what to render by describing in a JSON the widgets to render.
- The Flutter screen parse the JSON and build the widgets
Kind like HTML... but not really.
Example
The Server
Here is an example of JSON returned by the URL POST http://myapp.herokuapp.com/screens/profile
:
{
"type": "Screen",
"appBar": {
"type": "AppBar",
"attributes": {
"title": "Profile"
}
},
"child": {
"type": "Form",
"attributes": {
"padding": 10
},
"children": [
{
"type": "Input",
"attributes": {
"name": "first_name",
"value": "Ray",
"caption": "First Name",
"maxLength": 30
}
},
{
"type": "Input",
"attributes": {
"name": "last_name",
"value": "Sponsible",
"caption": "Last Name",
"maxLength": 30
}
},
{
"type": "Input",
"attributes": {
"name": "email",
"value": "ray.sponsible@gmail.com",
"caption": "Email *",
"required": true
}
},
{
"type": "Input",
"attributes": {
"type": "date",
"name": "birth_date",
"caption": "Date of Birth"
}
},
{
"type": "Input",
"attributes": {
"type": "Submit",
"name": "submit",
"caption": "Create Profile"
},
"action": {
"type": "Command",
"url": "https://myapp.herokuapp.com/commands/save-profile",
"prompt": {
"type": "Dialog",
"attributes": {
"type": "confirm",
"title": "Confirmation",
"message": "Are you sure you want to change your profile?"
}
}
}
}
]
}
}
The UI in Flutter
import 'package:flutter/material.dart';
import 'package:sdui/sdui.dart';
void main() async {
runApp(const MyApp());
}
class MyApp extends StatelessWidget {
const MyApp({Key? key}) : super(key: key);
@override
Widget build(BuildContext context) {
return MaterialApp(title: 'Demo', initialRoute: '/', routes: _routes());
}
Map<String, WidgetBuilder> _routes() =>
{
'/': (context) =>
const DynamicRoute(
provider: HttpRouteContentProvider(
'http://www.myapp.com/screens/profile'))
};
}
Screenshots
Screen | Date Picker | Alert Dialog |
---|---|---|
Widgets
In Flutter, UI is composed of a hierarchy of Widgets. A widget is a visual element on a screen.
SDUI described widgets with the following json structure:
{
"type": "...",
"attributes": {
"padding": 12,
"color": "#ff0000",
...
},
"children": [
...
]
}
type
: indicates the type of widgetattributes
: key/value pair of the attributes of the widget. Ex:caption
,color
,padding
,spacing
etc.children
: The list of children widgets
Widget Library
- Navigation widgets
- Layout widgets
- Images/Icons
- Input widgets
- Other
Global Variables
sduiErrorState
: Function for building the error state.sduiLoadingState
: Function for building the loading state.sduiProgressIndicator
: Function for building the progress indicator.sduiRouteObserver
: Route observer that reload each page on navigation.sduiAnalytics
: Analytics class. See SDUIAnalyticssduiCameras
: List of available cameras. Empty by default, must be initialized the application
Actions
With actions, you can:
- Execute a command on a server (Ex: Saver User Profile, Delete User Account etc.)
- Navigate to another screen.
- Prompt a message to user.
SDUI described actions with the following json structure:
{
"type": "...",
"attributes": {
...
},
...
"action": {
"type": "...",
"url": "...",
"prompt": {
"type": "...",
"title": "Confirmation",
"message": "Are you sure you want to change your profile?"
}
}
}
type
: Defines the type of action:Route
: To redirect to another routePage
: To redirect to another page, in the context of PageViewCommand
: Remote action to execute. The screen is associated with a URL that will execute the command, and redirect the user to the next screenShare
: Share a message to user via email/messenger/whatsapp etc.Navigate
: Navigate user to a web page
url
: is the URL associated with the actionroute:/..
: redirect users to previous routeroute:/~
: redirect users to 1st route- URL starting with
route:/<ROUTE_NAME>
redirect user the a named route. (Ex:route:/checkout
) - URL starting with
http://
orhttps
redirect user to a server driven page page:/<PAGE_NUMBER>
: redirect users to a given page.<PAGE_NUMBER>
is the page index (starting with0
).
replacement
: Fortype=Route
, this indicate if we replace the current view or navigate.parameters
: Parameters to add to the URL where to redirect tomessage
: Message to shareprompt
: Shows a Dialog before execute the actiontype
: The type of prompt (Exemple:Confirm
,Error
,Warning
,Information
)title
: Title of the alert box to openmessage
: Message to display to the user
Build your own Widget
You can integrate your own widget into sdui
.
Step 1: Create your instance of SDUIWidget
This is an example of widget that render a text with a margin and padding. The widget has the following attributes
text
: The text to displaypadding
: The padding valuemargin
: The margin value
class MyWidget extends SDUIWidget {
String text = '';
double padding = 10.0;
double margin = 10.0;
/// This method will be called by [SDUIParser] to read the widget attributes from the JSON data
@override
SDUIWidget fromJson(Map<String, dynamic>? json) {
text = json?['caption'] ?? '';
margin = json?['margin'] ?? 10.0;
padding = json?['padding'] ?? 10.0;
return this;
}
/// This method will be called when rendering the page to create the Flutter widget
@override
Widget toWidget(BuildContext context) =>
Container(
padding: EdgeInsets.all(padding),
margin: EdgeInsets.all(margin),
child: Text(
text,
style:
const TextStyle(fontWeight: FontWeight.bold, color: Colors.red),
),
);
}
Step 2: Register the widget
The Widget is registered into SDUI and associated with the type MyWidget
void main() async {
// Register 3rd party widget
SDUIWidgetRegistry.getInstance().register('MyWidget', () => MyWidget());
runApp(constMyApp());
}
class MyApp extends StatelessWidget {
// ...
}
Step 3: Add the widget into the JSONs
Here is an example of JSON with our 3rd party widget
{
"type": "Screen",
"appBar": {
"type": "AppBar",
"attributes": {
"title": "Home"
}
},
"child": {
"type": "Center",
"children": [
{
"type": "MyWidget",
"attributes": {
"caption": "3rd Party Widget",
"padding": 5.0,
"margin": 5.0
}
}
]
}
}