functional_widget 0.7.1

Build Status pub package pub package codecov

Widgets are cool. But classes are quite verbose:

class Foo extends StatelessWidget {
  final int value;
  final int value2;

  const Foo({Key key, this.value, this.value2}) : super(key: key);

  Widget build(BuildContext context) {
    return Text('$value $value2');

So much code for something that could be done much better using a plain function:

Widget foo(BuildContext context, { int value, int value2 }) {
  return Text('$value $value2');

The problem is, using functions instead of classes is not recommended:

... Or is it?

functional_widgets, is an attempt to solve this issue, using a code generator.

Simply write your widget as a function, decorate it with a @widget, and then this library will generate a class for you to use.

Example #

You write:

Widget foo(BuildContext context, int value) {
  return Text('$value');

It generates:

class Foo extends StatelessWidget {
  final int value;

  const Foo(this.value, {Key key}) : super(key: key);

  Widget build(BuildContext context) {
    return foo(context, value);

And then you use it:


How to use #

Install (builder) #

There are a few separate packages you need to install:

  • functional_widget_annotation, a package containing decorators. You must install it as dependencies.
  • functional_widget, a code-generator that uses the decorators from the previous packages to generate your widget. Install it inside builders, a Flutter specific field on your pubspec.yaml made for code-generators.

Your pubspec.yaml should looks like:

  functional_widget_annotation: ^0.5.0

  functional_widget: ^0.6.0

That's it! Flutter will automatically run the code generator when executing flutter build, flutter run or similar.

Install (build_runner) #

If your version of Flutter is too old, the previous installation method may not work. In that case it is possible to work with functional_widget by using build_runner package.

First add the following to your pubspec.yaml:

  functional_widget_annotation: ^0.5.0

  functional_widget: ^0.6.0
  build_runner: ^1.3.1

Then to run the generator, you must use build_runner:

flutter pub pub run build_runner watch

This will watch your source folder and run the code-generator whenever something changes.

Customize the output #

It is possible to customize the output of the generator by using different decorators or configuring default values in build.yaml file.

build.yaml change the default behavior of a configuration.

# build.yaml
          # Default values:
          debugFillProperties: false
          widgetType: stateless # or 'hook'
          equality: none # or 'identical'/'equal'

FunctionalWidget decorator will override the default behavior for one specific widget.

  debugFillProperties: true,
  widgetType: FunctionalWidgetType.hook,
  equality: FunctionalWidgetEquality.identical,
Widget foo() => Container();

debugFillProperties override #

Widgets can be override debugFillProperties to display custom fields on the widget inspector. functional_widget offer to generate these bits for your, by enabling debugFillProperties option.

For this to work, it is required to add the following import:

import 'package:flutter/foundation.dart';


(You write)

import 'package:flutter/foundation.dart';

Widget example(int foo, String bar) => Container();

(It generates)

class Example extends StatelessWidget {
  const Example(,, {Key key}) : super(key: key);

  final int foo;

  final String bar;

  Widget build(BuildContext _context) => example(foo, bar);
  void debugFillProperties(DiagnosticPropertiesBuilder properties) {
    properties.add(IntProperty('foo', foo));
    properties.add(StringProperty('bar', bar));

Generate different type of widgets #

By default, the generated widget is a StatelessWidget.

It is possible to generate a HookWidget instead (from

There are a few ways to do so:

  • Through build.yaml:
# build.yaml
          widgetType: hook
  • With @FunctionalWidget decorator:
@FunctionalWidget(widgetType: FunctionalWidgetType.hook)
Widget example(int foo, String bar) => Container();
  • With the shorthand @hwidget decorator:
Widget example(int foo, String bar) => Container();
class Example extends HookWidget {
  const Example(,, {Key key}) : super(key: key);

  final int foo;

  final String bar;

  Widget build(BuildContext _context) => example(foo, bar);

In any cases, flutter_hooks must be added as a separate dependency in the pubspec.yaml

  flutter_hooks: # some version number

operator== override #

It can be interesting for Widget to override operator== for performance optimizations.

functional_widget optionally allows overriding both operator== and hashCode based on the field used.

There are two different configurations:

  • none (default): Don't override anything
  • identical, overrides hashCode and operator== with the latter being implemented using identical to compare fields.
  • equal, similar to identical, but using == to compare fields.

It can be configured both through build.yaml:

# build.yaml
          equility: identical

or using @FunctionalWidget decorator:

@FunctionalWidget(equality: FunctionalWidgetEquality.identical)
Widget example(int foo, String bar) => Container();

All the potential function prototypes #

functional_widget will inject widget specific parameters if you ask for them. You can potentially write any of the following:

Widget foo();
Widget foo(BuildContext context);
Widget foo(Key key);
Widget foo(BuildContext context, Key key);
Widget foo(Key key, BuildContext context);

You can then add however many arguments you like after the previously defined arguments. They will then be added to the class constructor and as a widget field:

  • positional
Widget foo(int value) => Text(value.toString());


  • named:
Widget foo({int value}) => Text(value.toString());


Foo(value: 42);
  • A bit of everything:
Widget foo(BuildContext context, int value, { int value2 }) {
  return Text('$value $value2');


Foo(42, value2: 24);

0.7.0 #

  • support @required for Color and other dart:ui types

0.6.1 #

  • fixes invalid generation with generic functions

0.6.0 #

  • Updated analyzer version to work with flutter generate & co

0.5.0 #

  • Allows enabling/disable features though both build.yaml and a new decorator: FunctionalWidget
  • operator== and debugFillProperties overrides are now turned off by default.

0.4.0 #

  • Overrides debugFillProperties for an integration with the widget inspector. This requires adding a new import in your dart files: import 'package:flutter/foundation.dart';
  • Now overrides operator== and hashCode on the generated class.

The behavior is that the following function:

Widget foo(int foo, int bar) {
    return Container();

now generates the following overides:

int get hashCode => hashValues(foo, bar);

bool operator ==(Object o) =>
    identical(o, this) || (o is Foo && foo == && bar ==;

This is useful because overriding operator== prevents pointless rebuild when no parameter change.

0.3.0 #

  • Support function callbacks and generic functions:
Widget foo<T>(void onTap(T value)) {
    // do something
  • Updated support for HookWidget using new annotation @hwidget:
Widget foo() {
    final counter = useState(0);
    // do something

0.2.2 #

  • Readme update

0.2.1 #

  • Fix bug where types from dart:ui where generated as dynamic

0.2.0 #

  • Rename generator
  • Add documentation

0.1.0 #

  • Generate class documentation from the function documentation.
  • Pass down decorators from function parameter to class constructor

0.0.1 #

Initial release


import 'package:flutter/foundation.dart';
import 'package:functional_widget_annotation/functional_widget_annotation.dart';
import 'package:flutter/widgets.dart';

part 'main.g.dart';

// we create a widget using a widget decorated by `@widget`
Widget foo(int value) {
  return Container();

Widget example(int foo, String bar, {ValueChanged<bool> onChanged}) {
  return Container();

void main() => runApp(
      // we use the generated class
      const Foo(42),

Use this package as a library

1. Depend on it

Add this to your package's pubspec.yaml file:

  functional_widget: ^0.7.1

2. Install it

You can install packages from the command line:

with pub:

$ pub get

Alternatively, your editor might support pub get. Check the docs for your editor to learn more.

3. Import it

Now in your Dart code, you can use:

import 'package:functional_widget/builder.dart';
import 'package:functional_widget/findBeginToken.dart';
import 'package:functional_widget/function_to_widget_class.dart';
Describes how popular the package is relative to other packages. [more]
Code health derived from static analysis. [more]
Reflects how tidy and up-to-date the package is. [more]
Weighted score of the above. [more]
Learn more about scoring.

We analyzed this package on Feb 13, 2020, and provided a score, details, and suggestions below. Analysis was completed with status completed using:

  • Dart: 2.7.1
  • pana: 0.13.5

Health suggestions

Fix lib/function_to_widget_class.dart. (-2.96 points)

Analysis of lib/function_to_widget_class.dart reported 6 hints, including:

line 115 col 13: DO use curly braces for all flow control structures.

line 155 col 7: DO use curly braces for all flow control structures.

line 157 col 7: DO use curly braces for all flow control structures.

line 159 col 7: DO use curly braces for all flow control structures.

line 161 col 7: DO use curly braces for all flow control structures.

Fix lib/src/parameters.dart. (-0.50 points)

Analysis of lib/src/parameters.dart reported 1 hint:

line 53 col 20: 'isUndefined' is deprecated and shouldn't be used.

Maintenance issues and suggestions

Support latest dependencies. (-10 points)

The version constraint in pubspec.yaml does not support the latest published versions for 1 dependency (analyzer).


Package Constraint Resolved Available
Direct dependencies
Dart SDK >=2.1.0 <3.0.0
analyzer >=0.35.4 <0.37.0 0.36.4 0.39.4
build >=1.1.2 <2.0.0 1.2.2
build_config >=0.3.1+4 <1.0.0 0.4.2
code_builder >=3.2.0 <4.0.0 3.2.1
functional_widget_annotation ^0.5.0 0.5.1
meta ^1.1.6 1.1.8
source_gen ^0.9.4+1 0.9.4+4 0.9.4+7
Transitive dependencies
args 1.5.2
async 2.4.0
built_collection 4.3.2
built_value 7.0.9
charcode 1.1.3
checked_yaml 1.0.2
collection 1.14.12
convert 2.1.1
crypto 2.1.4
csslib 0.16.1
fixnum 0.10.11
front_end 0.1.19 0.1.29
glob 1.2.0
html 0.14.0+3
js 0.6.1+1
json_annotation 3.0.1
kernel 0.3.19 0.3.29
logging 0.11.4
matcher 0.12.6
node_interop 1.0.3
node_io 1.0.1+2
package_config 1.1.0 2.0.0
path 1.6.4
pub_semver 1.4.3
pubspec_parse 0.1.5
quiver 2.1.2+1
source_span 1.6.0
stack_trace 1.9.3
string_scanner 1.0.5
term_glyph 1.1.0
typed_data 1.1.6
watcher 0.9.7+13
yaml 2.2.0
Dev dependencies
build_runner 1.3.1
dart_style >=1.2.4 <1.2.5 1.2.9 1.3.3
mockito 4.0.0
pedantic 1.4.0 1.9.0
test ^1.5.3
test_coverage ^0.2.0