Skip to content

Textfield with FocusNode Rendered within an iFrame on Web Refuses to Lose Focus #155265

Closed

Description

@caleb-at-pieces

Steps to reproduce

  1. Create a flutter app with the following main.dart file (this is just a hello world flutter app that contains a textfield along with a focusnode):
import 'package:flutter/material.dart';

void main() {
  runApp(const MyApp());
}

class MyApp extends StatelessWidget {
  const MyApp({super.key});

  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        colorScheme: ColorScheme.fromSeed(seedColor: Colors.deepPurple),
        useMaterial3: true,
      ),
      home: const MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  const MyHomePage({super.key, required this.title});

  final String title;

  @override
  State<MyHomePage> createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  int _counter = 0;

  // Declare the FocusNode
  late FocusNode _focusNode;

  @override
  void initState() {
    super.initState();
    // Initialize the FocusNode
    _focusNode = FocusNode();
  }

  @override
  void dispose() {
    // Dispose of the FocusNode
    _focusNode.dispose();
    super.dispose();
  }

  void _incrementCounter() {
    setState(() {
      _counter++;
    });
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
        backgroundColor: Theme.of(context).colorScheme.inversePrimary,
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Text('You have pushed the button this many times:'),
            Text(
              '$_counter',
              style: Theme.of(context).textTheme.headlineMedium,
            ),
            const SizedBox(height: 20), // Add spacing
            // Add the TextField widget
            Padding(
              padding: const EdgeInsets.symmetric(horizontal: 40.0),
              child: TextField(
                focusNode: _focusNode,
                decoration: const InputDecoration(
                  labelText: 'Enter text',
                  border: OutlineInputBorder(),
                ),
              ),
            ),
          ],
        ),
      ),
      floatingActionButton: FloatingActionButton(
        onPressed: () {
          _incrementCounter();
          // Request focus when the button is pressed
          _focusNode.requestFocus();
        },
        tooltip: 'Increment',
        child: const Icon(Icons.add),
      ),
    );
  }
}
  1. Build the app with flutter build web
  2. Run this dart file to statically serve the flutter web application on port 3000:
import 'package:shelf/shelf_io.dart' as io;
import 'package:shelf_plus/shelf_plus.dart' show Pipeline;
import 'package:shelf_static/shelf_static.dart';
import 'package:shelf/shelf.dart';

Map<String, String> corsHeaders = {
  'Access-Control-Allow-Origin': '*',
  'Access-Control-Allow-Headers': '*',
};

Middleware cors = createMiddleware(responseHandler: (response) {
  return response.change(headers: corsHeaders);
}, requestHandler: (request) {
  if (request.method == 'OPTIONS') {
    return Response.ok(null, headers: corsHeaders);
  }
  return null;
});

void main() async {
  Pipeline pipeline = Pipeline();

  // pipeline = pipeline.addMiddleware(shelf.logRequests());
  pipeline = pipeline.addMiddleware(cors);

  var server = await io.serve(
    pipeline.addHandler(createStaticHandler('build/web', defaultDocument: 'index.html')),
    'localhost',
    3000,
    poweredByHeader: '',
  );

  /// This will remove default headers from the server.
  server.defaultResponseHeaders.removeAll('X-Frame-Options');
  // server.defaultResponseHeaders.add('X-Frame-Options', 'null');
}
  1. open this html file in your browser (this simply opens up an iframe to localhost:3000)
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Iframe Example</title>
    <style>
        body {
            margin: 0;
            padding: 0;
            display: flex;
            justify-content: center;
            align-items: center;
            height: 100vh;
        }
        iframe {
            width: 50vw; /* 50% of the viewport width */
            height: 100vh; /* 100% of the viewport height */
            border: none; /* Remove default border */
        }
    </style>
</head>
<body>
	<input placeholder="normal browser text input">
    <iframe src="http://localhost:3000"></iframe>
</body>
</html>
  1. click on the flutter app's TextField input widget
  2. Attempt to click on the browser input with the placeholder 'normal browser text input'
  3. The flutter TextField will momentarily lose focus, to only request it again, making it impossible to type into the other normal text input without clicking outside of the TextField in the flutter application

Expected results

I would expect that if you click outside of an iFrame that is a flutter web application, a focused TextField should properly lose focus

Actual results

The Flutter TextField does not lose focus until you click outside of the TextField within the flutter application

Code sample

Code sample

I provided the code sample earlier

Screenshots or Video

Screenshots / Video demonstration
Screen.Recording.2024-09-16.at.2.00.33.PM.mov

Logs

Logs
[Paste your logs here]

Flutter Doctor output

Doctor output
Doctor summary (to see all details, run flutter doctor -v):
[✓] Flutter (Channel stable, 3.24.3, on macOS 14.3.1 23D60 darwin-arm64, locale en-US)
[!] Android toolchain - develop for Android devices (Android SDK version 33.0.2)
    ✗ cmdline-tools component is missing
      Run `path/to/sdkmanager --install "cmdline-tools;latest"`
      See https://developer.android.com/studio/command-line for more details.
    ✗ Android license status unknown.
      Run `flutter doctor --android-licenses` to accept the SDK licenses.
      See https://flutter.dev/to/macos-android-setup for more details.
[!] Xcode - develop for iOS and macOS (Xcode 15.3)
    ✗ Unable to get list of installed Simulator runtimes.
[✓] Chrome - develop for the web
[✓] Android Studio (version 2022.2)
[✓] IntelliJ IDEA Ultimate Edition (version 2024.2.1)
[✓] IntelliJ IDEA Community Edition (version 2023.3.4)
[✓] VS Code (version 1.93.0)
[✓] Connected device (3 available)
[✓] Network resources

! Doctor found issues in 2 categories.

Activity

  1. darshankawar commented on Sep 17, 2024

    @darshankawar
    Member

    3. Run this dart file to statically serve the flutter web application on port 3000:

    @caleb-at-pieces Thanks for the detailed report. Can you please elaborate how to run this file ?
    Also, is there a way to replicate the reported behavior without above setup ?

  2. added
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Sep 17, 2024
  3. caleb-at-pieces commented on Sep 17, 2024

    @caleb-at-pieces
    Author

    Can you please elaborate how to run this file ?

    You can run this file simply by creating it (i.e name it server.dart), then from the root directory of the flutter project used to reproduce this run: dart server.dart

    Also, is there a way to replicate the reported behavior without above setup ?

    You could install the Pieces VS Code extension and see the same behavior within our Copilot input.

    In general, the important factors are having a FocusNode with a TextField that are then rendered within an iFrame on the web.

    Does that answer your question?

  4. removed
    waiting for responseThe Flutter team cannot make further progress on this issue until the original reporter responds
    on Sep 17, 2024
  5. darshankawar commented on Sep 18, 2024

    @darshankawar
    Member

    Yes, thanks for the update. Using the details provided, I was able to replicate the reported behavior on latest versions.

    Stable : 3.24.3
    Master : 3.26.0-1.0.pre.152
    
  6. added
    a: text inputEntering text in a text field or keyboard related problems
    frameworkflutter/packages/flutter repository. See also f: labels.
    f: focusFocus traversal, gaining or losing focus
    has reproducible stepsThe issue has been confirmed reproducible and is ready to work on
    platform-webWeb applications specifically
    fyi-webFor the attention of Web platform team
    on Sep 18, 2024
  7. 10 remaining items

  8. nank1ro commented on Nov 27, 2024

    @nank1ro

    hey guys i have the same problem and would like to use the workaround. but i cannot use html since i am using wasm and therefore have to use import 'package:web/web.dart' as web; can anyone tell me what the equivalen of html.window.onBlur.listen((event) { html.document.activeElement?.blur(); }); is using the web package?

    here it is the wasm compatible workaround, provided by @jezell on Twitter

    import 'package:web/web.dart';
    import 'dart:js_interop';
    
    class MyApp extends StatefulWidget {
      const MyApp({super.key});
    
      @override
      State<MyApp> createState() => _MyAppState();
    }
    
    class _MyAppState extends State<MyApp> {
      @override
      void initState() {
        super.initState();
        window.addEventListener('blur', onBlur.toJS);
      }
    
      @override
      void dispose() {
        window.removeEventListener('blur', onBlur.toJS);
        super.dispose();
      }
    
    
      // Workaround for https://github.com/flutter/flutter/issues/155265
      void onBlur(Event e) {
        (document.activeElement as HTMLElement?)?.blur();
      }
      
      ...
    }
  9. added
    P1High-priority issues at the top of the work list
    and removed
    P2Important issues not at the top of the work list
    on Mar 19, 2025
  10. self-assigned this
    on Apr 9, 2025
  11. added
    r: fixedIssue is closed as already fixed in a newer version
    on Apr 28, 2025
  12. github-actions commented on May 12, 2025

    @github-actions

    This thread has been automatically locked since there has not been any recent activity after it was closed. If you are still experiencing a similar issue, please open a new bug, including the output of flutter doctor -v and a minimal reproduction of the issue.

  13. locked as resolved and limited conversation to collaborators on May 12, 2025
  14. moved this to Done (PR Merged) in FlutterFlow Blockerson May 21, 2025
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Labels

P1High-priority issues at the top of the work lista: text inputEntering text in a text field or keyboard related problemscustomer: googleVarious Google teamsf: focusFocus traversal, gaining or losing focusfound in release: 3.24Found to occur in 3.24found in release: 3.26Found to occur in 3.26frameworkflutter/packages/flutter repository. See also f: labels.has reproducible stepsThe issue has been confirmed reproducible and is ready to work onplatform-webWeb applications specificallyr: fixedIssue is closed as already fixed in a newer versionteam-webOwned by Web platform teamtriaged-webTriaged by Web platform teamworkaround availableThere is a workaround available to overcome the issue

Type

No type

Projects

No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions