Skip to content

All About customRender

Matthew Whitaker edited this page Dec 26, 2019 · 3 revisions

How To Use customRender

Version 1.0.0 reintroduces support for a customRender function, which allows you to render elements however you want so that you can control every last pixel of your HTML-to-Widget app.

This page will attempt to give you the resources you need to make full use of customRender for whatever your needs are.

Simple Usage

The customRender callback takes a Map<String, CustomRender> like so:

Html(
  data: ...,
  customRender: {
    "MyElement": (_, __, ___, ____) {
      return MyWidget();
    }
  }
),

Parameters

The previous example would be the most basic usage of customRender. It uses none of the available parameters and simply returns a Widget. The available parameters are defined in the CustomRender according to this typedef (this can be found in lib/html_parser.dart):

typedef CustomRender = Widget Function(
  RenderContext context,
  Widget parsedChild,
  Map<String, String> attributes,
  dom.Element element,
);

Explanation and examples of each of the parameters follow.

RenderContext context

The context contains some useful information about the current state of the tree where your element is being rendered. There are three parts of a RenderContext:

  • BuildContext buildContext: The BuildContext of the Html widget.
  • HtmlParser parser: This contains all the configuration information for the Html widget, including potentially useful values such as shrinkWrap, onLinkTap, and onImageError.
  • Style style: This contains the Style of the current element. See the Style wiki page for more info.

Example: A button that navigates to a new page

Html(
  data: "<button>Next Page</button>
  customRender: {
    "button": (context, _, __, ___) {
      return MaterialButton(
        onPressed: () {
          Navigator.of(context.buildContext).pushNamed('/new-page');
        },
        child: Text("My Custom Button"),
      );
    },
  },
),

Widget parsedChild

Sometimes you only need to modify the way one element is displayed, but don't want to deal with parsing and rendering each of your custom element's children. In this case, you can use the parsedChild parameter. The parsedChild parameter gives you a Widget with all of the custom element's children parsed by the default parser. It even supports nested customRendered Widgets!

Example: A button that renders its children

Html(
  data: "<button>Next Page</button>
  customRender: {
    "button": (context, child, _, __) {
      return MaterialButton(
        onPressed: () {
          Navigator.of(context.buildContext).pushNamed('/new-page');
        },
        child: child,
      );
    },
  },
),

Map<String, String> attributes

This can be used to directly access the attributes of an HTML element if you don't want to deal with the dom.Element object. All values are strings.

Example: A Flutter logo with and without the horizontal attribute

Html(
  data: "Normal: <flutter></flutter><br />Horizontal: <flutter horizontal></flutter>"
  customRender: {
    "flutter": (context, child, attributes, _) {
      return FlutterLogo(
        style: (attributes['horizontal'] != null)
          ? FlutterLogoStyle.horizontal
          : FlutterLogoStyle.markOnly,
        textColor: context.style.color,
        size: context.style.fontSize.size * 5,
      );
    },
  },
),

dom.Element element

This attribute can be used if you want to do everything yourself. It provides access to the dom.Element node that customRender is being run on (which in turn provides access to the entire DOM tree). Most basic use-cases probably won't need to worry about this parameter, but it can be helpful for doing more advanced custom elements.

Example: using the element parameter

Coming Soon!

Additional Examples

Coming soon!