Open MarvinHannott opened 4 years ago
The problem is that with var
the variable is available through window.
, but it isn't available with either let
or const
. https://stackoverflow.com/a/28776236/374798
We either need to document that these aren't accessible through Dart, or find a new way to access them.
cc @sigmundch
The problem is that with
var
the variable is available throughwindow.
, but it isn't available with eitherlet
orconst
. https://stackoverflow.com/a/28776236/374798We either need to document that these aren't accessible through Dart, or find a new way to access them.
cc @sigmundch
You are right, that didn't occure to me. And the same goes for ES2015 classes as I have noticed. It might be worth mentioning that only ES5 is fully supported and that Babel should be used.
minor update: I just updated the title and merged a few issues here to track them all in one place.
ES6 let
, class
, and const
are not hoisted to the window scope so they are not visible to JS-interop. We need to properly document what are the recommended ways to access these symbols.
See also #40102, #35737
You are right, that didn't occure to me. And the same goes for ES2015 classes as I have noticed. It might be worth mentioning that only ES5 is fully supported and that Babel should be used.
Note that you shouldn't have to convert to ES5 with babel, it would be sufficient to expose the symbols that can't be hoisted. For example:
class MyClass {...}
window.MyClass = MyClass;
would work too.
I am looking for the solution for the issue #35737. It directed me here for more discussion on the issue. Is there any suggestion for that issue solution.
Sorry actual issue has been marked as closed. So keeping the comment here for solution.
Thanks in advance.
@RaghuMudem - the example in #35737 was exporting an ES6 class:
export class HelloWorld {
sayHello() {
return "HelloWorld"
}
}
So the suggestion in https://github.com/dart-lang/sdk/issues/39995#issuecomment-643000112 applies here. That is, add in JavaScript an extra line that actually exposes the class definition as a top-level member on the window:
export class HelloWorld {
sayHello() {
return "HelloWorld"
}
}
window.HelloWorld = HelloWorld;
This will make it possible for JS-interop to find that definition.
Was this the pattern you were looking for?
Hi @sigmundch, Thanks for your reply.
I am loading a html content with video element in a IFrameElement using HtmlElementView. In my Javascript method, i am trying to get the video element by document.getElementById('video')
;. But it always giving me null.
And the same video is able to find initApp method. initApp method is called with the following code.
document.addEventListener('DOMContentLoaded', initApp);
And my complete javascript code is here. I also added comments to make it clear on the problematic areas.
var PlayerHandler = /** @class */ (function () {
function PlayerHandler() {}
PlayerHandler.prototype.bark = function () {
console.log("bark ..");
};
PlayerHandler.prototype.videoTest = function (url) {
const video = document.getElementById('video'); **// This is always return null.**
console.log("videoTest video "+video +" window.video "+window.video); **//window.video also null. Wanted video object here**
};
return PlayerHandler;
}());
var myModule = { PlayerHandler: PlayerHandler };
window.PlayerHandler = PlayerHandler;
function initApp() {
initPlayer();
}
async function initPlayer() {
// Create a Player instance.
const video = document.getElementById('video'); **//This always returns video element**
window.video = video;
console.log('initPlayer video '+video);
}
document.addEventListener('DOMContentLoaded', initApp);
Here is the console logs:
initPlayer video [object HTMLVideoElement]
bark ..
videoTest video null window.video null
Would be very helpful if anyone can suggest me to get the video element in the places mentioned above.
Hi @sigmundch, Thanks for your reply. I am loading a html content with video element in a IFrameElement using HtmlElementView. In my Javascript method, i am trying to get the video element by
document.getElementById('video')
;. But it always giving me null.And the same video is able to find initApp method. initApp method is called with the following code.
document.addEventListener('DOMContentLoaded', initApp);
And my complete javascript code is here. I also added comments to make it clear on the problematic areas.
var PlayerHandler = /** @class */ (function () { function PlayerHandler() {} PlayerHandler.prototype.bark = function () { console.log("bark .."); }; PlayerHandler.prototype.videoTest = function (url) { const video = document.getElementById('video'); **// This is always return null.** console.log("videoTest video "+video +" window.video "+window.video); **//window.video also null. Wanted video object here** }; return PlayerHandler; }()); var myModule = { PlayerHandler: PlayerHandler }; window.PlayerHandler = PlayerHandler; function initApp() { initPlayer(); } async function initPlayer() { // Create a Player instance. const video = document.getElementById('video'); **//This always returns video element** window.video = video; console.log('initPlayer video '+video); } document.addEventListener('DOMContentLoaded', initApp);
Here is the console logs:
initPlayer video [object HTMLVideoElement] bark .. videoTest video null window.video null
Would be very helpful if anyone can suggest me to get the video element in the places mentioned above.
I found a workaround for this. Posting the clue here for others who has the similar problem.
Description about the solution:
final div = html.DivElement()..id = 'player-iframe-root';
html.IFrameElement()..id = 'player-iframe'
<video id="video" controls autoplay></video>
_element = html.IFrameElement()
..style.border = 'none'
..id = 'player-iframe'
..srcdoc =
""" <!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<style>
video {
width: 100%;
height: auto;
}
</style>
</head>
<body style="background-color:white;">
<video id="video" controls autoplay></video>
<!-- Your application source: -->
<script src="../../../web/player-handler.js"></script>
</body>
</html>
""";
final div = html.DivElement()..id = 'player-iframe-root';
final container = div..append(_element);
// ignore:undefined_prefixed_name
ui.platformViewRegistry.registerViewFactory(
'player-$textureId',
(int viewId) => container,
);
Widget build(BuildContext context) {
return Scaffold(
appBar: null,
body: Container(
child: HtmlElementView(
viewType: 'player-$textureId',
),
),
);
}
And fetching the video element inside my js intero call on videoTest() method call.
class PlayerHandler {
videoTest() {
/*The tree order of the html should be <div id=player-iframe-root><iframe id=player-iframe><video/></iframe></div> .
And this html is created dynamically in dart code as mentioned in point 4 */
var div = document.getElementById('player-iframe-root');
var iframe = div.querySelector("#player-iframe");
this._video = iframe.contentWindow.document.getElementsByTagName("video")[0]; **//Video element available here and ready to use :)**
console.log('this._video '+this._video);
}
}
window.PlayerHandler = PlayerHandler;
@JS()
library playerHandler;
import 'package:js/js.dart';
@JS("PlayerHandler") class PlayerHandler { external factory PlayerHandler(); external void videoTest(); }
Hope this clue can help for someone who is working for **Flutter-web-iframe-video-js-interop** combination :)
I am getting dart.global.MyClass is not a constructor if I add script elements dynamically but works fine if script is added directly to index.html.
I have requirement to add scripts dynamically only. Can you please help me with the same?
@MaryaBelanger @srujzs - FYI - another user hit this issue again this week. It may be worth adding a section about this in some of our upcoming site changes (maybe under some kind of FAQ?)
Describe the issue you're seeing External getters don't work with JS
let
andconst
declarations. It does work, however, withvar
declaration.Does it happen in Dartium or when compiled to JavaScript? Compile to JavaScript with
webdev build
.dart --version
2.7pubspec.lock
0.6.1+1Failing code:
Working code: