SchemaForm class

StatelessWidget for building forms dynamically from JSON schema interpretation. It takes two JSONs to build the form. A third JSON can be used as a data source, which in turn needs to be in accordance with the data schema.

Examples

Minimal

  JsonSchemaBloc jsonSchemaBloc = JsonSchemaBloc(formContext: context);
  SchemaForm schemaForm = SchemaForm(jsonSchemaBloc: jsonSchemaBloc);

  File layoutSchemaFile = new File("layoutSchema.json");
  File dataSchemaFile = new File("dataSchema.json");
  File dataValueFile = new File("dataValue.json");

  String layoutSchemaContent = layoutSchemaFile.readAsStringSync();
  String dataSchemaContent = dataSchemaFile.readAsStringSync();
  String dataValueContent = dataValueFile.readAsStringSync();

  Map<String, dynamic> layoutSchemaMap = json.decode(layoutSchemaContent);
  Map<String, dynamic> dataSchemaMap = json.decode(dataSchemaContent);
  Map<String, dynamic> dataValueMap = json.decode(dataValueContent);

  JsonSchema dataJsonSchema = JsonSchema.createSchema(dataSchemaMap);

  jsonSchemaBloc.add(LoadLayoutSchemaEvent(layout: layoutSchemaMap));
  jsonSchemaBloc.add(LoadDataSchemaEvent(dataSchema: dataJsonSchema));
  jsonSchemaBloc.add(LoadDataEvent(data: dataValueMap));

Complete

import 'dart:convert';
import 'dart:io';

import 'package:flutter/material.dart';
import 'package:http/http.dart' as http;
import 'package:json_schema/json_schema.dart';
import 'package:schema_form/bloc/json_schema_bl.dart';
import 'package:schema_form/schema_form.dart';

void main() => runApp(MyApp());

enum FileLocate { asset, storage, url }

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    final appTitle = 'Flutter JsonSchema Demo';
    JsonSchemaBloc jsonSchemaBloc = JsonSchemaBloc(formContext: context);

    loadSchemasFrom(
      FileLocate.asset,
      context,
      jsonSchemaBloc,
    );

    return MaterialApp(
      locale: Locale("pt", "BR"),
      title: appTitle,
      home: Scaffold(
        appBar: AppBar(
          title: Text(appTitle),
        ),
        drawer: Drawer(
          child: ListView(
            // Important: Remove any padding from the ListView.
            padding: EdgeInsets.zero,
            children: <Widget>[
              DrawerHeader(
                child: Text(appTitle),
                decoration: BoxDecoration(
                  color: Colors.blue,
                ),
              ),
              ListTile(
                title: Text('Load from Asset'),
                onTap: () => loadSchemasFrom(
                  FileLocate.asset,
                  context,
                  jsonSchemaBloc,
                ),
              ),
              ListTile(
                title: Text('Load from Storage'),
                onTap: () => loadSchemasFrom(
                  FileLocate.storage,
                  context,
                  jsonSchemaBloc,
                ),
              ),
              ListTile(
                title: Text('Load from URL'),
                onTap: () => loadSchemasFrom(
                  FileLocate.url,
                  context,
                  jsonSchemaBloc,
                ),
              ),
            ],
          ),
        ),
        body: SchemaForm(jsonSchemaBloc: jsonSchemaBloc),
      ),
    );
  }

  void loadSchemasFrom(FileLocate fileLocate, BuildContext context,
      JsonSchemaBloc jsonSchemaBloc) {
    loadJsonFrom(fileLocate, context, "testLayoutSchema.json").then(
            (Map<String, dynamic> layoutSchema) =>
            jsonSchemaBloc.add(LoadLayoutSchemaEvent(layout: layoutSchema)));

    loadJsonFrom(fileLocate, context, "testDataSchema.json").then(
            (Map<String, dynamic> jsonMap) =>
            jsonSchemaBloc.add(
                LoadDataSchemaEvent(dataSchema: JsonSchema.createSchema(jsonMap))));

    loadJsonFrom(fileLocate, context, "testDataValue.json").then(
            (Map<String, dynamic> dataValue) =>
            jsonSchemaBloc.add(LoadDataEvent(data: dataValue)));
  }

  Future<Map<String, dynamic>> loadJsonFrom(FileLocate fileLocate,
      BuildContext context, String fileName) async {
    switch (fileLocate) {
      case FileLocate.asset:
        return await loadJsonFromAsset(context, 'assets/$fileName');
      case FileLocate.storage:
        return await loadJsonFromStorage(
            context, '/storage/emulated/0/Json/files/$fileName');
      case FileLocate.url:
        return await loadJsonFromUrl(context,
            'https://legytma-platform-open-api-back.herokuapp.com/schema/mongo/$fileName');
      default:
        throw "Não implementado!";
    }
  }

  Future<Map<String, dynamic>> loadJsonFromAsset(BuildContext context,
      String filePath) async {
    print("filePath: $filePath");

    String content = await DefaultAssetBundle.of(context).loadString(filePath);

    print("content: $content");

    Map<String, dynamic> jsonMap = json.decode(content);

    return jsonMap;
  }

  Future<Map<String, dynamic>> loadJsonFromStorage(BuildContext context,
      String filePath) async {
    print("filePath: $filePath");

    File file = new File(filePath);

    if (file.existsSync()) {
      String content = file.readAsStringSync();

      print("content: $content");

      Map<String, dynamic> jsonMap = json.decode(content);

      return jsonMap;
    }

    throw "File not found!";
  }

  Future<Map<String, dynamic>> loadJsonFromUrl(BuildContext context,
      String filePath) async {
    print("filePath: $filePath");

    String username = '';
    String password = '';
    String basicAuth =
        'Basic ' + base64Encode(utf8.encode('$username:$password'));
    print('basicAuth: $basicAuth');

    http.Response response = await http.get(Uri.encodeFull(filePath), headers: {
      "Accept": "application/json",
      "Authorization": basicAuth,
    });

    if (response.statusCode == 200) {
      Map<String, dynamic> jsonMap = json.decode(response.body);

      return jsonMap;
    }

    throw "${response.statusCode} - ${response.reasonPhrase}: ${response.body}";
  }
}

Expected Outcome

Constructors

SchemaForm({Key key, JsonSchemaBloc jsonSchemaBloc })
Create a SchemaForm using JsonSchemaBloc. [...]

Properties

jsonSchemaBloc JsonSchemaBloc
SchemaForm Business Logic Object. [...]
final
hashCode → int
The hash code for this object. [...]
read-only, inherited
key → Key
Controls how one widget replaces another widget in the tree. [...]
final, inherited
runtimeType → Type
A representation of the runtime type of the object.
read-only, inherited

Methods

build(BuildContext context) → Widget
Describes the part of the user interface represented by this widget. [...]
createElement() → StatelessElement
Creates a StatelessElement to manage this widget's location in the tree. [...]
inherited
debugDescribeChildren() → List<DiagnosticsNode>
Returns a list of DiagnosticsNode objects describing this node's children. [...]
@protected, inherited
debugFillProperties(DiagnosticPropertiesBuilder properties) → void
Add additional properties associated with the node. [...]
inherited
noSuchMethod(Invocation invocation) → dynamic
Invoked when a non-existent method or property is accessed. [...]
inherited
toDiagnosticsNode({String name, DiagnosticsTreeStyle style }) → DiagnosticsNode
Returns a debug representation of the object that is used by debugging tools and by DiagnosticsNode.toStringDeep. [...]
inherited
toString({DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String
Returns a string representation of this object.
inherited
toStringDeep({String prefixLineOne: '', String prefixOtherLines, DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String
Returns a string representation of this node and its descendants. [...]
inherited
toStringShallow({String joiner: ', ', DiagnosticLevel minLevel: DiagnosticLevel.debug }) → String
Returns a one-line detailed description of the object. [...]
inherited
toStringShort() → String
A short, textual description of this widget.
inherited

Operators

operator ==(dynamic other) → bool
The equality operator. [...]
inherited