Table of Contents
json_dynamic_widget_plugin_components
Table of Contents
Live Example
Introduction
Plugin to the JSON Dynamic Widget which allows to combine the set of JSON widgets into one -> component.
About
Dependency loaders
Dependency is a combination of a name
and a version
.
Loaders are used to load components in a raw format from the different sources.
Each loader needs to implement the load
method:
Future<String?> load(Dependency dependency, BuildContext context);
Currently supported loaders:
- AssetDependencyLoader : Loads the dependency from the assets. Can be configured via
AssetPathResolver
which specifies howDependency
is resolved to the path. - MemoryDependencyLoader : Loads the dependency from the in-memory map.
- CachedDependencyLoader : Caches the result of the child dependency loader.
Dependency version resolvers
Dependency version resolvers allow to define custom version resolving strategies.
For example in case of the missing version string it is possible to define
the logic of looking for the latest
version.
Each loader needs to implement the resolve method:
Future<String> resolve(String name, String? version, BuildContext context);
Currently supported version resolvers:
- RequiredDependencyVersionResolver : Requires the version string to be present in the dependency and throw the error if it's not.
Component spec
Component specification defines the version, name and the set of inputs and outputs. It's content is just the group of widgets which are used to build the component.
Fields definition:
- name - component name
- version - component version
- inputs - list of input variables and their default values
- outputs - list of output variables that can be used outside of the component
- content - group of the widgets which uses the inputs and produces the outputs variables
Example:
name: centered_text
version: 1.0.0
inputs:
- name: text
description: The text value
defaultValue: ''
outputs: []
content:
type: center
listen:
- text
args:
child:
type: text
args:
text: "${'This text is centered:' + text ?? ''}"
Component values encapsulation
Each component can have it's own values.
To avoid name collisions each component have also it's own, separate registry.
Each component allow to define it's own inputs and outputs:
inputs
- the input variables of the component, that are available for the component registry. Not passing any values on caller side means that the default values will be used. If the value of the input usesvariables
then each update will be passed to the component registry.outputs
- the output variables of the component, that can be exported to caller registry. Not passing any values means on caller side means that specific variable is not exported to the caller registry.
For e.g.
"type": "component",
"args": {
"name": "header",
"inputs": {
"text": "Some text for the header"
},
"outputs": {
"header_click_count" : "header1_click_count"
}
}
Using the Plugin
- Bind the plugin.
import 'package:json_dynamic_widget/json_dynamic_widget.dart';
import 'package:json_dynamic_widget_plugin_components/json_dynamic_widget_plugin_components.dart';
void main() {
// Ensure Flutter's binding is complete
WidgetsFlutterBinding.ensureInitialized();
// ...
// Get an instance of the registry
var registry = JsonWidgetRegistry.instance;
// Bind the plugin to the registry. This is necessary for the registry to
// find the widget provided by the plugin
JsonComponentsPluginRegistrar.registerDefaults(registry: registry).withLoader(
CachedDependencyLoader(
cachedLoader: AssetDependencyLoader(
pathResolver: DirAssetPathResolver(
basePath: 'assets/components', // {components_path}
ext: Ext.json,
extByDependencyName: {
'centered_text': Ext.yaml,
},
),
),
),
);
// ...
}
- Create the JSON file with component data and place it in
{components_path}/{component_name}/{version}.json
.
// {components_path}/custom_text_input/1.0.0.json
{
"name": "custom_text_input",
"version": "1.0.0",
"inputs": [
{
"name": "label",
"description": "The text input label",
"defaultValue": ""
},
{
"name": "hint",
"description": "The text input hint",
"defaultValue": ""
}
],
"outputs": [
{
"name": "text_input",
"description": "The text input value"
}
],
"content": {
"type": "text_form_field",
"id": "text_input",
"args": {
"decoration": {
"hintText": "${hint}",
"labelText": "${label}",
"suffixIcon": {
"type": "icon_button",
"args": {
"icon": {
"type": "icon",
"args": {
"icon": {
"codePoint": 57704,
"fontFamily": "MaterialIcons",
"size": 50
}
}
},
"onPressed": "${set_value('text_input','')}"
}
}
},
"validators": [
{
"type": "required"
}
]
}
}
}
- Use the component in the
json_dynamic_widget
.
"type": "component",
"args": {
"name": "custom_text_input",
"version": "1.0.0",
"inputs": {
"label": "First name",
"hind": "John"
},
"outputs": {
"text_input": "first_name_input_value"
}
}