Handling complex HTML in Flutter

Displaying nested table view in Flutter

Tanmoy karmakar
5 min readFeb 10, 2023

I have been working on the Helpwise application, an unified messaging inbox application that helps businesses connect all their mail, SMS, and social media platforms into one app and manage their customer communication.

One of the app's features is to connect Gmail inbox and receive all emails in the same app. Now Helpwise had been using web view in the app to display all the email threads so we never faced an issue till now.

We decided to move the Webview into native flutter code, i.e handling the email data in the app itself. Now, As far my knowledge I thought we can easily handle the HTML data and use the flutter_html package to render the HTML.

Simple right? What can possibly go wrong? 😂

It's not so simple my friend. The issue was after implementing the code most of the emails looked great but Newsletters, signatures, and tables were nowhere to be found.

I was shocked. I don't have any idea about the web how can I fix it?

So I searched the whole web and found out that the package does not properly handle complex tables and in order to render the HTML the package simply displays TABLE_SECTION to denote that area.

This bug was opened in march, 2021 and has still not been fixed.

I need help. what can I do now?

Solution 1

My first solution was to use the html_editor_enhanced which is a text editor to inject the HTML code and use the editor as a view-only widget.

I was able to do that but why it didn't work?

The editor if disabled still needs to be given a specific height. If I give it the height it needs I restrict the view area of the email.

Not acceptable.

Now?

I am depressed and thought we have to move back to Webview again 😭

Eureka moment!!!!

While discussing the issue with my senior. We were trying to find out some kind of solution that we can agree on and suddenly he suggested

why not render the HTML as a Webview?

wait what? HTML can be rendered in Webview? Doesn’t a URL is required to display a Webview?

As I came to know now it's not 😅

Actual solution

So Let's see how we implemented it,

We used the flutter_inappwebview package

to render the HTML and it worked flawlessly.

Thank you for reading we are all done…….😍😍

Still reading that means it's not so easy 😅

Even though we are able to show the HTML we still had to prove a specific height. That means the user needs to scroll inside the email to see the whole content which is even inside a listview builder.

Now to make the Webview height dynamic?

After hours of searching, I was able to find a StackOverflow thread that adds specific HTML to get the height

but the problem was after implementing the solution, the height was not consistent for some the height was 0 and no error came up but if I give an initial height I was able to see the email.

Now I have some idea that the HTML code is the problem here. we are good with Flutter.

Step 2 — Get the height consistently

When checking whether we are able to print the Webview height we added a console log and just printed the height and surprisingly we were getting the correct height every time.

Now it struck me why not just retrieve the log and convert it to double and use it, simple right?

As it turned out it was 😅


AnimatedContainer(
duration: Duration(milliseconds: 500),
height: height + (height == 0 ? 0 : 50),
child: InAppWebView(
initialData: InAppWebViewInitialData(data: html),
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
supportZoom: false,
javaScriptEnabled: true,
disableHorizontalScroll: false,
disableVerticalScroll: true,
),
),
onLoadError: (controller, url, code, message) =>
print("onLoadError: $url, $code, $message"),
onLoadHttpError:
(controller, url, statusCode, description) => print(
"onLoadHttpError: $url, $statusCode, $description"),
onConsoleMessage: (controller, consoleMessage) {
print('height: ${height}');
height = double.parse(consoleMessage.message);
setState(() {});
},
),
);
html = """
<html lang="en">
<meta name="viewport" content="width=device-width user-scalable=no zoom=1.1">
<style>img {max-width: 100%; height: auto}</style>
<body>
<div><div class="htmlWrapper container" id="_flutter_target_do_not_delete">$html</div></div>
<script>
function outputsize() {
console.log(document.getElementById("_flutter_target_do_not_delete").offsetHeight);
window.postMessage('flutterTargetHeight', document.getElementById("_flutter_target_do_not_delete").offsetHeight);
}
new ResizeObserver(outputsize).observe(_flutter_target_do_not_delete)
outputsize()
</script>
""";

And with this, I was able to get the correct height every time the HTML loaded along with a sweet animation.

Hurray!!! We did it…….

Thanks for reading this article ❤️

My udemy course: Appwrite with Flutter Beginner course 2023 is live use

https://www.udemy.com/course/appwrite-with-flutter-beginner-course-2023/

to get the course!!!

reach me at LinkedIn !!

other links: https://linktr.ee/tanmoykarmakar

Support me at,

--

--