h function

VElement h(
  1. String tag, [
  2. Object? arg1,
  3. Object? arg2,
  4. Object? arg3,
])

Creates a virtual node VElement with the specified tag and arguments.

The arguments mean the following element properties:

  • Attributes
  • Children
  • Event listeners

Arguments may be specified in any order, must not be duplicated, or may not be specified at all.

Example:

return h(
  'div',
  {'class': 'w3-border-bottom', 'style': 'border-color:#BCAE5F!important;'},
   SectionListWidget(),
);

Implementation

VElement h(
  String tag, [
  Object? arg1,
  Object? arg2,
  Object? arg3,
]) {
  Map<String, Object>? attributes;
  List<VNode>? children;
  Map<String, void Function(Event event)>? listeners;
  var isAttributesAllowed = true;
  var isChildrenAllowed = true;
  var isListenersAllowed = true;
  var isFinished = false;
  final arguments = [arg1, arg2, arg3];
  for (var i = 0; i < arguments.length; i++) {
    final argument = arguments[i];
    if (argument == null) {
      isFinished = true;
    } else if (isFinished) {
      _error(
          "No processing is provided for an argument specified after a 'null' argument",
          [arg1, arg2, arg3],
          i,
          {
            'attributes': attributes,
            'children': children,
            'listeners': listeners,
          });
    } else if (argument is Iterable<Object?>) {
      _checkArgument(
          isChildrenAllowed,
          'children',
          [arg1, arg2, arg3],
          i,
          {
            'attributes': attributes,
            'children': children,
            'listeners': listeners,
          });
      isChildrenAllowed = false;
      final list = <VNode>[];
      for (final data in argument) {
        final vNode = _createNode(data);
        list.add(vNode);
      }

      children = list;
    } else if (argument is String) {
      _checkArgument(
          isChildrenAllowed,
          'children',
          [arg1, arg2, arg3],
          i,
          {
            'attributes': attributes,
            'children': children,
            'listeners': listeners,
          });
      isChildrenAllowed = false;
      final vNode = VNodeFactory.createVNode(argument);
      children = [vNode];
    } else if (argument is VNode) {
      _checkArgument(
          isChildrenAllowed,
          'children',
          [arg1, arg2, arg3],
          i,
          {
            'attributes': attributes,
            'children': children,
            'listeners': listeners,
          });
      isChildrenAllowed = false;
      children = [argument];
    } else if (argument is Component) {
      _checkArgument(
          isChildrenAllowed,
          'children',
          [arg1, arg2, arg3],
          i,
          {
            'attributes': attributes,
            'children': children,
            'listeners': listeners,
          });
      isChildrenAllowed = false;
      final vNode = VNodeFactory.createVNode(argument);
      children = [vNode];
    } else if (argument is Map<String, void Function(Event event)>) {
      _checkArgument(
          isListenersAllowed,
          'listeners',
          [arg1, arg2, arg3],
          i,
          {
            'attributes': attributes,
            'children': children,
            'listeners': listeners,
          });
      isListenersAllowed = false;
      listeners = argument;
    } else if (argument is Map<String, dynamic>) {
      _checkArgument(
          isAttributesAllowed,
          'attributes',
          [arg1, arg2, arg3],
          i,
          {
            'attributes': attributes,
            'children': children,
            'listeners': listeners,
          });
      isAttributesAllowed = false;
      attributes = {};
      for (final key in argument.keys) {
        final value = argument[key];
        if (value == null) {
          _error(
              "The value of an element attribute '$key' must not be 'null'",
              [arg1, arg2, arg3],
              i,
              {
                'attributes': attributes,
                'children': children,
                'listeners': listeners,
              });
        }

        attributes[key] = value as Object;
      }
    } else if (argument is Map && argument.isEmpty) {
      isAttributesAllowed = false;
      attributes = {};
    } else {
      _error(
          "Unable to process argument of type '${argument.runtimeType}'",
          [arg1, arg2, arg3],
          i,
          {
            'attributes': attributes,
            'children': children,
            'listeners': listeners,
          });
    }
  }

  final result = VElement(tag);
  if (attributes != null) {
    result.attributes.addAll(attributes);
  }

  if (listeners != null) {
    result.listeners.addAll(listeners);
  }

  if (children != null) {
    result.children.addAll(children.map(VNodeEntry.new));
  }

  return result;
}