Flutter Web + iFrame: The Basic Guide Using HtmlElementView

Welcome back to the magical world of Flutter Web and iFrames! Today, we're going to delve deeper into loading HTML files, exploring options and controls for iFrames, and handling multiple iFrames within a Flutter app. Buckle up, it's going to be a fun ride!

What Are We Trying to Achieve?

In this blog, we aim to demystify the process of embedding HTML content into Flutter Web applications using iFrames with the HtmlElementView widget. Whether you’re a seasoned Flutter developer or just starting, understanding this fundamental technique opens doors to integrating dynamic external content seamlessly into your apps.

What Can You Gain?

By the end of this guide, you will:

  • Master HTML Integration: Learn how to embed external web content like maps, videos, and more directly into your Flutter Web app.

  • Enhance User Experience: Provide richer and more interactive experiences by seamlessly integrating third-party content.

  • Expand Your Flutter Toolkit: Add another powerful tool to your arsenal for building cross-platform apps with Flutter.

Whether you’re looking to enrich your app with dynamic content or simply exploring new capabilities of Flutter Web, this guide equips you with the foundational knowledge to get started effectively.

Loading an HTML File into an iFrame

Loading an HTML file into an iFrame is straightforward. You simply set the src attribute of the iFrame to the URL of the HTML file. Let's start with an example:

  1. Register the iFrame with an HTML File

     import 'dart:html';
     import 'dart:ui' as ui;
     import 'package:flutter/material.dart';
    
     void main() {
       // Register the iFrame element with an HTML file.
       ui.platformViewRegistry.registerViewFactory(
         'html-iframe',
         (int viewId) => IFrameElement()
           ..width = '100%'
           ..height = '600'
           ..src = 'assets/sample.html'
           ..style.border = 'none',
       );
    
       runApp(MyApp());
     }
    

    In this example, assets/sample.html is the path to your HTML file. Make sure to include the HTML file in your pubspec.yaml:

     flutter:
       assets:
         - assets/sample.html
    
  2. UseHtmlElementView in Your Widget Tree

     class MyApp extends StatelessWidget {
       @override
       Widget build(BuildContext context) {
         return MaterialApp(
           home: Scaffold(
             appBar: AppBar(title: Text('Flutter Web HTML iFrame Example')),
             body: Center(
               child: Container(
                 width: MediaQuery.of(context).size.width * 0.8,
                 height: 600,
                 child: HtmlElementView(viewType: 'html-iframe'),
               ),
             ),
           ),
         );
       }
     }
    

Options and Controls for iFrames

iFrames come with a plethora of options and controls. Here are some of the most useful ones:

  • Width and Height: Control the dimensions of the iFrame.

  • Scrolling: Control whether the iFrame should have scrollbars.

  • Sandbox: Add restrictions to the content within the iFrame for security.

  • Srcdoc: Provide HTML content directly instead of using an external file.

Let's enhance our example with some of these options:

ui.platformViewRegistry.registerViewFactory(
  'html-iframe',
  (int viewId) => IFrameElement()
    ..width = '100%'
    ..height = '600'
    ..src = 'assets/sample.html'
    ..style.border = 'none'
    ..scrolling = 'auto'
    ..sandbox.add('allow-scripts'),
);

Handling Multiple iFrames

What if you want more than one iFrame? Easy peasy! Just register multiple iFrames and use them in your widget tree.

  1. Register Multiple iFrames

     ui.platformViewRegistry.registerViewFactory(
       'html-iframe-1',
       (int viewId) => IFrameElement()
         ..width = '100%'
         ..height = '300'
         ..src = 'assets/sample1.html'
         ..style.border = 'none',
     );
    
     ui.platformViewRegistry.registerViewFactory(
       'html-iframe-2',
       (int viewId) => IFrameElement()
         ..width = '100%'
         ..height = '300'
         ..src = 'assets/sample2.html'
         ..style.border = 'none',
     );
    
  2. Use Multiple iFrames in Your Widget Tree

     class MyApp extends StatelessWidget {
       @override
       Widget build(BuildContext context) {
         return MaterialApp(
           home: Scaffold(
             appBar: AppBar(title: Text('Flutter Web Multiple iFrames Example')),
             body: SingleChildScrollView(
               child: Column(
                 children: [
                   Text('Welcome to our amazing app!', style: TextStyle(fontSize: 24)),
                   SizedBox(height: 20),
                   Container(
                     width: MediaQuery.of(context).size.width * 0.8,
                     height: 300,
                     child: HtmlElementView(viewType: 'html-iframe-1'),
                   ),
                   SizedBox(height: 20),
                   Text('Below is another embedded content:', style: TextStyle(fontSize: 20)),
                   SizedBox(height: 20),
                   Container(
                     width: MediaQuery.of(context).size.width * 0.8,
                     height: 300,
                     child: HtmlElementView(viewType: 'html-iframe-2'),
                   ),
                   SizedBox(height: 20),
                   ElevatedButton(
                     onPressed: () {
                       // Button action
                     },
                     child: Text('Click Me'),
                   ),
                 ],
               ),
             ),
           ),
         );
       }
     }
    

Full Example: Integrating iFrame with Other Widgets

Now, let’s bring everything together in a full example where the iFrame is part of a larger Flutter UI with various widgets.

import 'dart:html';
import 'dart:ui' as ui;
import 'package:flutter/material.dart';

void main() {
  // Register multiple iFrames
  ui.platformViewRegistry.registerViewFactory(
    'html-iframe-1',
    (int viewId) => IFrameElement()
      ..width = '100%'
      ..height = '300'
      ..src = 'assets/sample1.html'
      ..style.border = 'none',
  );

  ui.platformViewRegistry.registerViewFactory(
    'html-iframe-2',
    (int viewId) => IFrameElement()
      ..width = '100%'
      ..height = '300'
      ..src = 'assets/sample2.html'
      ..style.border = 'none',
  );

  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      home: Scaffold(
        appBar: AppBar(title: Text('Flutter Web iFrame Extravaganza')),
        body: SingleChildScrollView(
          child: Column(
            children: [
              Text('Welcome to our amazing app!', style: TextStyle(fontSize: 24)),
              SizedBox(height: 20),
              Container(
                width: MediaQuery.of(context).size.width * 0.8,
                height: 300,
                child: HtmlElementView(viewType: 'html-iframe-1'),
              ),
              SizedBox(height: 20),
              Text('Below is another embedded content:', style: TextStyle(fontSize: 20)),
              SizedBox(height: 20),
              Container(
                width: MediaQuery.of(context).size.width * 0.8,
                height: 300,
                child: HtmlElementView(viewType: 'html-iframe-2'),
              ),
              SizedBox(height: 20),
              ElevatedButton(
                onPressed: () {
                  // Button action
                },
                child: Text('Click Me'),
              ),
            ],
          ),
        ),
      ),
    );
  }
}

Conclusion

Using iFrames in Flutter Web can enhance your app by allowing you to embed external content seamlessly. Whether you're loading HTML files, controlling various options, or handling multiple iFrames, the HtmlElementView widget makes it all possible.

Remember, iFrames are like guests at a party – treat them well, but don't let them overstay their welcome. Happy coding, and may your Flutter Web apps be ever more dynamic and engaging!

2
Subscribe to my newsletter

Read articles from Shankar Kakumani directly inside your inbox. Subscribe to the newsletter, and don't miss out.

Written by

Shankar Kakumani
Shankar Kakumani