flutter / flutter

Flutter makes it easy and fast to build beautiful apps for mobile and beyond
https://flutter.dev
BSD 3-Clause "New" or "Revised" License
166.34k stars 27.54k forks source link

Add ability to pass variables into embedded web applications #139822

Closed justincbeck closed 6 months ago

justincbeck commented 11 months ago

Is there an existing issue for this?

Use case

Add the ability to pass variables from a host application into an embedded flutter application. I have been trying to find documentation on this and also trying to figure out how I might make this work and have been unable.

I have a Node web application into which I have embedded a simple Flutter application using the technique outlined here. I can find no way to pass a variable into the embedded web application.

As an alternative, I am using local storage in the browser to pass a variable. This works in the simple case but won't work in the more complex case and isn't secure.

Proposal

I am proposing that variables can be passed to the embedded application in some manner, perhaps like this:

    window.addEventListener('load', function(ev) {
      let target = document.querySelector('#flutter_target');
      let myVariable = 'this is my variable';
      _flutter.loader.loadEntrypoint({
        onEntrypointLoaded: async function (engineInitializer) {
          let appRunner = await engineInitializer.initializeEngine({
            hostElement: target,
          });
          await appRunner.runApp(myVariable);
          console.log('Flutter app running!');
        },
      });
    });

...and then inside the Flutter code, something like this:

void main(someVariable) async {
  print(someVariable);

  runApp(
    const MyApp();
  );
}

Where the output of the print statement is this is my variable.

NOTE: I noticed that if I put a variable as an attribute of the main method, that I can print it out but it is always an empty array.

yjbanov commented 11 months ago

We're actively working on adding multi-view support, and a single custom element is just a special case of having one view in the app. In the multi-view mode you will be able to pass variables when creating the view. Technically, that's different from runApp because runApp may execute Dart code without any views at all. However, if view parameters are sufficient for your use-case, then it will be available (hopefully) in the next stable release.

If you still have a good use-case for runApp parameters as opposed to view parameters, please respond and we'll prioritize it as a new feature request.

johnpryan commented 11 months ago

You could also try using JS interop with a global variable. Here's a snippet using static interop via the dart:js_interop library (which works when you compile to JS or Wasm).

  <script>
    var appData = {
      'foo': 'bar',
    };

    window.addEventListener('load', function(ev) {
      // Download main.dart.js
      _flutter.loader.loadEntrypoint({
        serviceWorker: {
          serviceWorkerVersion: serviceWorkerVersion,
        },
        onEntrypointLoaded: function(engineInitializer) {
          engineInitializer.initializeEngine().then(function(appRunner) {
            appRunner.runApp();
          });
        }
      });
    });
  </script>
import 'package:flutter/material.dart';
import 'dart:js_interop';

@JS()
@staticInterop
@anonymous
class AppData {}

extension AppDataExtension on AppData {
  external String get foo;
}

@JS()
@staticInterop
external AppData get appData;

void main() {
  print('appData.foo = ${appData.foo}');
  runApp(const MyApp());
}
justincbeck commented 11 months ago

We're actively working on adding multi-view support, and a single custom element is just a special case of having one view in the app. In the multi-view mode you will be able to pass variables when creating the view. Technically, that's different from runApp because runApp may execute Dart code without any views at all. However, if view parameters are sufficient for your use-case, then it will be available (hopefully) in the next stable release.

If you still have a good use-case for runApp parameters as opposed to view parameters, please respond and we'll prioritize it as a new feature request.

I can wait for this change. I have several options as work arounds including what @johnpryan suggested. Thank you.

ditman commented 10 months ago

There's some discussion about this here:

ditman commented 6 months ago

The above has landed, for embedded, multiview apps we can now pass an initialData parameter from JS to each view. The documentation will be incoming soon, here's a demo:

Here's the source code.

yjbanov commented 6 months ago

This is done.

justincbeck commented 6 months ago

Awesome! Thanks so much!

nikhil-s-b commented 6 months ago

@yjbanov Is there a document that we can refer to? We are trying to understand how to setup a web multi view

ditman commented 6 months ago

@nikhil-s-b not yet; I'll start working on it soon. There's a design doc:

github-actions[bot] commented 6 months ago

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.