ezFlap — Reactive Markup for Flutter
Flutter is pretty great.
I found it easy enough to pick up and become productive at, but coming from a web development background, I missed things like:
- Using markup to define the content of screen.
- Using separate style sheets to design screens.
- The fully automatic reactivity (i.e. to avoid having to call setState) that we get from modern frameworks like Vuejs and Angular.
I decided to experiment with carrying some web development, and particularly Vuejs development concepts over to the Flutter world.
The ezFlap Library
ezFlap uses a simple, XML-based language, that allows to define a hierarchy of Flutter widgets, using tags and attributes.
This language is called: ZML.
When developing with ezFlap:
- Widgets have a ZML block instead of a build function.
- ezFlap annotations are used to decorate fields and methods in the widget to give them various capabilities.
With the help of the Dart build_runner tool, ezFlap generates the widget’s build method and additional supporting code automatically, based on the ZML and annotations provided in the widget.
In this article, I will give a high level overview of ezFlap.
The full documentation is available in https://www.ezflap.io.
Let’s see what an ezFlap version of the Flutter Counter application might look like.
The MyApp widget:
The MyHomePage widget:
A few points of interest:
- Tags that start with an upper-case letter map to the class with that name (often a widget).
- Tags that start with a lower-case letter map to a named parameter of the constructor of the class they are in.
- Attributes with the z-bind prefix are another way to pass data to the constructor of the class they belong to. Their names correspond to the constructor’s parameters, and their values are Dart expressions.
- The EzField annotation makes a field available in the ZML, so that it can, for example, be used inside z-bind attribute values.
- The EzMethod annotation makes a method available in the ZML (e.g. as an event handler, passed to a hosted widget using the z-on attribute).
ezFlap Style Sheets: ZSS
ezFlap allows to separate the content of the screen from its design. If ZML is like HTML, then ZSS is like CSS.
ZSS consists of selectors, with a CSS-like syntax, and effects, which are injected into ZML tags that are matched by the selector, as named parameters.
Here is a simple widget with a single ZSS rule:
Here is a slightly more complicated example, that also shows selector extension (similar to the
& operator in SCSS):
In the above examples, the attributes used in the selectors are all hard-coded in the ZML tags. In cases like this, ezFlap matches them in build time, when it generates the code of the build function.
It is also possible to use dynamic attribute values.
In the following example, we have a Container with a
z-attr:status="status"attribute. This attribute is set dynamically, at runtime, to the current value of the
status EzField field, and its color is set dynamically according to the ZSS:
ezFlap offers many more features:
- Conditional rendering using ZML attributes (similar to v-if and v-show in Vuejs).
- Two-way data binding with a hosted widget (similar to v-model in Vuejs).
- Computed methods (similar to Vuejs).
- Delayed rendering.
- Emitting and capturing events between widgets.
- Life-cycle hooks.
- Annotations for dependency injection.
- Annotations for making custom reactive data entities.
- Annotations for automatic, infinitely-recursive JSON serialization and deserialization.
- Easy access to hosted widgets (similar to refs in Vuejs).
- Slots (similar to Vuejs).
- Watches (to invoke a method when a reactive data changes).
- Widget inheritance for advanced use-cases.
- Interoperability with native Flutter code; ezFlap widgets can use, and be used by, native Flutter code.
- Extensions to the built-in Flutter testing system to allow easy mocking of dependency-injected services and hosted widgets.
- And more!
The full documentation is here.
It covers the entire ezFlap library, and has over 200 examples.
It is accompanied by the ezflap_docs Github repository.
This repository contains an Example Player that can be used to find and run most of the examples (and of course also tweak them to try ezFlap out):