Package - AppDaddy-Software-Solutions-Inc/framework-markup-language GitHub Wiki
<PACKAGE/> : Widget
The <PACKAGE/>
or <PKG/>
element dynamically loads custom content (functions and viewable content) into FML. Packages can be created using either inline flutter dart
code or downloaded from a remote source compiled to .evc
byte code. Pre-compiled .evc code is more efficient.
<PACKAGE/>
is a third party integration of the dart_eval
package written by Ethan Blake
. Many thanks!
To learn more about building your own dynamic content and linking it into FML, refer to the flutter_eval
package on flutter's pub.dev
site.
As noted, flutter_eval
supports most flutter material widgets and dart syntax. Please refer to the language reference
support page. All custom classes inside of the flutter
code must be wrapped inside of a $Closure
or an approprate bridge json defined.
Name | Type | Default | Description |
---|---|---|---|
url | String | The url of the .evc compiled flutter package |
|
dart | String | The pre-compiled flutter package |
|
defer | bool | false | Packages, by default, are compiled (inline dart) or downloaded (.evc byte code) before the `' is rendered. This can sometimes be slow and delay content loading while the package is being processed. In some situations we may wish to defer loading of the package until it is required. This is typical when the content is a widget. |
Name | Type | Description |
---|---|---|
{$id} | String | The $id is a property which allows the user to pass the id of the containing widget to the |
{$get} | Function | The {$get} callback Function can be accessed by passing it as a parameter to a function or class in the package. It can then be called from within the package to retrieve values from the FML framework using var value = get(<id>.<property>) where value is a dynamic return value and <id>.<property> is an observable. |
{$set} | Function | The {$set} callback Function can be accessed by passing it as a parameter to a function or class in the package. It can then be called from within the package to set a value in the FML framework. User set(<id>.<property>, value) <id>.<property> is an observable and value is the value to set. |
<PKG id="pkg1" url="/plugins/my_plugin_package.evc" name="package:my_plugin_package/main.dart"/>
<FORM>
<!-- Custom Function Example -->
<TEXT id="t1" value="=pkg1.MyFunctions.sayHello('Cruel World')"/>
<BUTTON label="Click Me" onclick="t1.set(pkg1.MyFunctions.sayGoodbye('Cruel World'))"/>
<!-- Custom Widget -->
<TEXT id="text" value="This is what shows in the red box. get('text') is called from within the dynamic widget."/>
<WIDGET id="w1" plugin="pkg1.MyWidget({$id},{$get},{$set})"/>
<!-- Custom Form Field Control -->
<TEXT id="t2" value="{f1.value}"/>
<FIELD id="f1" plugin="pkg1.MyField({$id},{$get},{$set})" value="999"/>
</FORM>
// @ the terminal prompt,
// run => dart_eval compile -o my_plugin_package.evc
library my_plugin_package;
export 'main.dart' show MyWidget, MyField, MyEvals;
import 'package:flutter/material.dart';
// ex. <WIDGET id="w1" plugin="pkg1.MyWidget({$id},{$get},{$set})"/>
// where 'pkg1' is <PKG id="pkg1" url="/plugins/my_plugin_package.evc" name="package:my_plugin_package/main.dart"/>,
// {$id} is the id of the encapsulating <WIDGET/>, {$get} is the get function, and {$set} is the set function
class MyWidget extends StatelessWidget {
final String id;
final Function set;
final Function get;
const MyWidget(this.id, this.get, this.set);
@override
Widget build(BuildContext context) {
var text = get("text") ?? "not found";
return Container(color: Colors.red, width: 200, height: 200, child: Text(text));
}
}
// ex. <FIELD id="f1" plugin="pkg1.MyField({$id},{$get},{$set})" value="999"/>
// where 'pkg1' is <PKG id="pkg1" url="/plugins/my_plugin_package.evc" name="package:my_plugin_package/main.dart"/>,
// {$id} is the id of the encapsulating <FIELD/>, {$get} is the get function, and {$set} is the set function
class MyField extends StatelessWidget {
final String id;
final Function set;
final Function get;
const MyField(this.id, this.get, this.set);
@override
Widget build(BuildContext context) {
var value = get('$id.value') ?? "";
var view = TextField(maxLength: 200, onChanged: onChanged, controller: TextEditingController(text: value));
return view;
}
void onChanged(String? value) => set('$id.value', value);
}
class MyFunctions {
// ex. <TEXT id="t1" value="=pkg1.MyFunctions.sayHello('Cruel World')"/>
// where 'pkg1' is <PKG id="pkg1" url="/plugins/my_plugin_package.evc" name="package:my_plugin_package/main.dart"/>
static String sayHello(String? message) {
return 'Hello $message';
}
// ex. <BUTTON label="Click Me" onclick="t1.set(pkg1.MyFunctions.sayGoodbye('Cruel World'))"/>
// where 'pkg1' is <PKG id="pkg1" url="/plugins/my_plugin_package.evc" name="package:my_plugin_package/main.dart"/>
static String sayGoodbye(String? message) {
return 'Goodbye $message';
}
}
Compile the above code to .evc byte code from the command line using:
$dart_eval compile -o my_plugin_package.evc
<PKG id="pkg1" name="package:example/main.dart">
<dart>
<![CDATA[
import 'package:flutter/material.dart';
class MyWidget extends StatelessWidget {
MyWidget(this.name);
final String name;
@override
Widget build(BuildContext context) {
return Padding(padding: EdgeInsets.all(5.0),
child: Column(mainAxisSize: MainAxisSize.min,
children: [Container(color: Colors.red,child: Text('The name is ' + name))],
mainAxisAlignment: MainAxisAlignment.center,
crossAxisAlignment: CrossAxisAlignment.center));
}
}
]]>
</dart>
</PKG>
<!-- Custom Widget -->
<BOX expand="false" border="all" bordercolor="green" padding="50" radius="5" margin="10" center="true">
<WIDGET id="w1" plugin="pkg1.MyWidget('Name 1')"/>
<WIDGET id="w2" plugin="pkg1.MyWidget('Name 2')"/>
</BOX>
</FML>