Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Package:web usage for migration #229

Open
ebala96 opened this issue Apr 29, 2024 · 9 comments
Open

Package:web usage for migration #229

ebala96 opened this issue Apr 29, 2024 · 9 comments
Labels
type-question A question about expected behavior or functionality

Comments

@ebala96
Copy link

ebala96 commented Apr 29, 2024

I'm doing a migration to 'package:web' and 'dart:js_interop'. I'm currently using the context object from the 'dart:js' package to store functions in the window object reference. However, I've noticed that there's no direct way to access the context from the 'package:web'.

I need help with this migration. Below is the code snippet I need to migrate

void _connectJsToFlutter({VoidCallback? then}) {
    js.context['$jsToDartConnectorFN$iframeViewType'] = (js.JsObject window) {
      jsWindowObject = window;
      for (final cb in widget.dartCallBacks) {
        jsWindowObject[cb.name] = cb.callBack;
      }

      jsWindowObject[webOnClickInsideIframeCallback] = (onClickCallbackObject) {
        _handleOnIframeClick(onClickCallbackObject as String);
      };

      webViewXController.connector = jsWindowObject;

      then?.call();
    };
}

Can you provide the correct usage of context and JsObject needed for the migration?

@srujzs srujzs added the type-question A question about expected behavior or functionality label Apr 29, 2024
@srujzs
Copy link
Contributor

srujzs commented Apr 29, 2024

globalContext is the dart:js_interop equivalent with JSObject being the equivalent to JsObject. Also note that we use static interfaces instead of class wrappers now with dart:js_interop.

A simple migration might look like the following:

import 'dart:js_interop';
import 'dart:js_interop_unsafe'; // to dynamically set properties using []=
...
void _connectJsToFlutter({VoidCallback? then}) {
    globalContext['$jsToDartConnectorFN$iframeViewType'] = (JSObject window) {
      JSObject jsWindowObject = window;
      for (final cb in widget.dartCallBacks) {
        jsWindowObject[cb.name] = cb.callBack.toJS;
      }

      jsWindowObject.setProperty(webOnClickInsideIframeCallback.toJS, (String onClickCallbackObject) {
        _handleOnIframeClick(onClickCallbackObject);
      }.toJS);

      webViewXController.connector = jsWindowObject;

      then?.call();
    };
}

It's a little difficult to tell what the types of some of these objects are, but a few key points here are:

  • you need to use either a primitive type or an interop type when making a call to JS
  • functions are passed using .toJS, which will return a new JSFunction that will call the original function. These functions can also only take in/return primitive types and interop types

For more information, look at https://dart.dev/interop/js-interop/usage and https://dart.dev/interop/js-interop/js-types

@ebala96
Copy link
Author

ebala96 commented Apr 30, 2024

Thank you. Understood the usage now.

Also could you let me know if I am doing the right way of doing onbeforeunload.

window.onbeforeunload = () async{
      //my code snippet
}.toJS;

Or can I use a event listener to perform the same.

window.addEventListener('beforeunload', (JSAny data) {
      //my code snippet
    }.toJS);

@srujzs
Copy link
Contributor

srujzs commented Apr 30, 2024

Yup, both should work (although that first one should take in the event as a parameter and I'm also not sure the async is necessary). You can also use EventStreamProvider in lib/src/helpers/events/streams.dart if you'd rather work with Streams: EventStreamProvider<BeforeUnloadEvent>('beforeunload').forTarget(window).

@ebala96
Copy link
Author

ebala96 commented May 3, 2024

Also I am doing callMethod from JsObject and passing List<dynamic> params as the second parameter.
JsObject if from 'dart:js' package

For migration I am using JSObject from dart:js_interop_unsafe and doing a callMethodVarArgs call and passing the List params.
How can I pass the List as [List<JSAny?>? arguments]?

Also, am I using the correct method from JSObject?

@srujzs
Copy link
Contributor

srujzs commented May 3, 2024

It's better practice to define an interface for the JSObject using an extension type than use dart:js_interop_unsafe (see https://dart.dev/interop/js-interop/usage#interop-type-members on how to write an interop extension type), but if you don't statically know the method name, then dart:js_interop_unsafe and callMethodVarArgs is ok as the replacement.

How can I pass the List as [List<JSAny?>? arguments]?

What does the List contain? You'll need to convert the contents of the List to JSAnys. If it's a List<String> for example, you can do a list.map((e) => e.toDart).toList() to get a List<JSString>. Or if you have a literal e.g. ['hello', 'world'], you can just do ['hello'.toJS, 'world'.toJS] instead.

@ebala96
Copy link
Author

ebala96 commented May 3, 2024

List contains dynamic type values.
It contains string, boolean, number and Set/List.

@srujzs
Copy link
Contributor

srujzs commented May 3, 2024

Assuming the nested Sets/Lists all contain types that can be converted as well (primitives or other nested structures), one thing you could try is using jsify which will convert all the entries in that list recursively.

List<dynamic> list = ...;
List<JSAny?> jsList = list.map((e) => jsify(e)).toList();

@ebala96
Copy link
Author

ebala96 commented May 9, 2024

Where can I get more information or examples of JS interop usage other than https://dart.dev/interop/js-interop/usage?

@srujzs
Copy link
Contributor

srujzs commented May 10, 2024

Besides the js-interop page and its subsections, I'd look at some examples of existing migrations like those in https://github.com/flutter/packages (just grep for dart:js_interop) or https://github.com/flutter/devtools. We have some tests in the Dart SDK as well that might be useful: https://github.com/dart-lang/sdk/tree/main/tests/lib/js/static_interop_test.

Of course, if you feel like you still have some questions, feel free to ask. If you want to provide feedback on what documentation might be useful for you or others, you can do so in https://github.com/dart-lang/site-www. There's some ongoing work there to get a "getting started" tutorial.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
type-question A question about expected behavior or functionality
Projects
None yet
Development

No branches or pull requests

2 participants