Angular2 listen for global event - javascript

I've a third party script, which is not a npm module. So what I did, is I added it as a normal script to my index.html, because there is just no way around that.
<script src="https://myExternalScript.js"></script>
Once this myExternalScript.js loaded, it will download another js file, which then calls a function called onDiagramReady(). I've to implement onDiagramLoaded(). So to be able to catch this event, I've added my onDiagramLoaded() to my index.html. Which look like this:
function onDiagramReady() {
window.dispatchEvent(new CustomEvent('onDiagramReady', {detail: this.Diagram}));
}
In my component I've a #HostListener to be able to get the context into it. This looks like this:
#HostListener('window:onDiagramReady', ['$event'])
onReactomeDiagramReadyListener(event) {
//magic in my component 🎉
}
So this was working perfectly fine in Angular 2.0, but now I get an error in my console:
It is still working, but I don't know what to do about this error. Is there maybe a better way to make a function available to the global scope?

Related

Blazor WebAssembly call a JS function on error without using observer

With Blazor WebAssembly, when an error occurs, it shows the div with id "blazor-error-ui".
Is it possible to call a JS function when an error occur without using an observer and without using the framework ?
I've dug a little deeper and it seems that the Blazor WebAssembly framework calls window.Module.printErr() whenever a runtime error happens.
I'm not a JavaScript expert, but it seems like you could intercept that call.
A naive implementation that proves the method would be to replace your script to load blazor webassembly in the index.html with this:
<script src="_framework/blazor.webassembly.js" autostart="false"></script>
<script>
document.addEventListener("DOMContentLoaded", function() {
Blazor.start().then(function () {
window["OLDprintErr"] = window.Module.printErr
window.Module.printErr = e => {
window["OLDprintErr"](e) // invoke standard behaviour
alert(e) // invoke custom behaviour - just an alert for POC
}
})
})
</script>
With that in place, any runtime errors will pop an alert and trigger the standard blazor-error-ui - of course you can replace the call to alert with whatever you want.
It is beyond my JS skills to do this in a nicer way, but I leave that to the reader / comments below - if any decent JS improvements appear I will edit the answer.

Vuejs eventbus triggers multiple times due to webpack import outport?

In a vuejs project I use the vue eventbus like this. Emitting this event:
icontag.addEventListener('click', testFunction, false)
function testFunction () {
console.log('click1')
Events.$emit('click2')
}
And receiving it in another module I get as output one click1, but multiple click2's. It looks very much like every time there is some code which requires webpack import/ export it triggers an additional result on the eventbus of the same event..., or something..., since in chrome devtools the related code close to the click2's has code like __WEBPACK_IMPORTED_MODULE_5__util nearby.
Any idea what is going on?
EDIT:
I think it might have been a 'corrupted hot-reload setup'. After rebuilding the dev hot-reload build, the issue seems gone now. Still interested in similar experiences as the issue was pretty ugly and persistent.
I think the comment from Bert is right. You can actually register many times the same eventhandlers on the same event.
Try removing the eventhandler before adding it again.
icontag.removeEventListener("click", testFunction);
icontag.addEventListener('click', testFunction, false)
function testFunction () {
console.log('click1')
Events.$emit('click2')
}

Qt function runJavaScript() does not execute JavaScript code

I am trying to implement the displaying of a web page in Qt. I chose to use the Qt WebEngine to achieve my task. Here's what I did :
Wrote a sample web page consisting of a empty form.
Wrote a JS file with just an API to create a radio button inside the form.
In my code, it looks like this :
View = new QWebEngineView(this);
// read the js file using qfile
file.open("path to jsFile");
myJsApi = file.Readall();
View->page()->runjavascript (myjsapi);
View->page()->runjavascript ("createRadioButton(\"button1\");");
I find that the runJavaScript() function has no effect on the web page. I can see the web page in the output window, but the radio button I expected is not present. What am I doing wrong?
I think you will have to connect the signal loadFinished(bool) of your page() to a slot, then execute runJavaScript() in this slot.
void yourClass::mainFunction()
{
View = new QWebEngineView(this);
connect( View->page(), SIGNAL(loadFinished(bool)), this, SLOT(slotForRunJS(bool)));
}
void yourClass::slotForRunJS(bool ok)
{
// read the js file using qfile
file.open("path to jsFile");
myJsApi = file.Readall();
View->page()->runJavaScript(myjsapi);
View->page()->runJavaScript("createRadioButton(\"button1\");");
}
I had this problem, runJavascript didn't have any effect. I had to put some html content into the view (with page().setHtml("") before running it.
Check the application output, it might contain JavaScript errors. Even if your JS code is valid, you might encounter the situation where the script is run before DOMContentLoaded event, that is document.readyState == 'loading'. Therefore, the DOM might not be available yet, as well as variables or functions provided by other scripts. If you depend on them for your code to run, when you detect this readyState, either wait for the event or try calling the function later, after a timeout. The second approach with timeout might be needed if you need to get the result of the code execution, as this can be done only synchronously.

Javascript Runtime Error: 'Application is undefined'

I need to know if this is correct. I'm just beginning in app development using WinJS. I've identified the source of the problem and got rid of it but I don't know if that's the correct method.Please help!
// Optimize the load of the application and while the splash screen is
// shown, execute high priority scheduled work.
ui.disableAnimations();
var p = ui.processAll().then(function () {
//return nav.navigate(nav.location || Application.navigator.home, nav.state);
return nav.navigate(nav.location || app.local, nav.state)
}).then(function () {
return sched.requestDrain(sched.Priority.aboveNormal + 1);
}).then(function () {
ui.enableAnimations();
});
The problem is in the first .then(). The commented line was the default line, I've changed it for the app to work.I've absolutely no idea what it is.Please tell me what it means and what is changed. By the way, 'app' is WinJS.Application and Application is a WinJS namespace in navigator.js where the home property is located.
This error would suggest that navigator.js isn't being loaded by the time this code is executed. The Application namespace, which is entirely arbitrary and unrelated to WinJS.Application, is defined only in navigator.js, so if that file isn't loaded that namespace won't exist.
A WinJS namespace, by the way, is just a formalization of a module pattern in JavaScript that helps you keep the global namespace from getting cluttered. Declaring a namespace like navigator.js does it:
WinJS.Namespace.define("Application", {
PageControlNavigator: WinJS.Class.define(
just creates a single object in the global namespace called "Application" and then defines members for it. (You can change "Application" to anything you want, by the way. Nothing else in navigator.js relies on it, and navigator.js is something that comes from the app templates in Visual Studio and isn't part of WinJS itself.)
So again, my suspicion is that you don't have (or whatever the proper path is) in your default.html, the path to it isn't correct, or that perhaps it's being loaded after the other code is trying to execute. Try setting breakpoints on WinJS.Namespace.define and see if that file is loaded and the breakpoint gets hit.

QtWebKit bridge: call JavaScript functions

I am writing a hybrid application with HTML interface and Python code.
I can access Python functions via a shared object:
pythonPart.py:
class BO(QObject):
def __init__(self, parent=None):
super(BO, self).__init__(parent)
#Slot(str)
def doStuff(self, txt):
print(txt)
bridgeObj = BO()
# init stuff and frame...
frame.addToJavaScriptWindowObject( 'pyBridge', bridgeObj )
frame.evaluateJavaScript('alert("Alert from Python")')
frame.evaluateJavaScript('testMe()')
frame.evaluateJavaScript('alert("Starting test");testMe();alert("Test over")')
jsPart.js:
function testMe() { alert('js function testMe called'); }
pyBridge.doStuff("bla");
testMe();
Calling Python functions from JS works, as does calling testMe from JS. Calling "standard" JS functions like alert from Python works, too.
The last two Python lines won't:
evaluateJavaScript("testMe()") doesn't do anything at all.
The last line executes the first alert and won't continue after that.
EDIT: I already tried having some time.sleep() between loading and calling the evaluateJavaScript and I'm loading the webpage from the local machine.
The most likely problem is that the JavaScript just isn't loaded yet. Adding time.sleep() calls doesn't help for that, those will also block the Qt event loop from continuing, not just your Python code.
Try waiting for the page to have fully loaded instead, for example (using the loadFinished signal:
def onLoad():
frame.evaluateJavaScript('testMe()')
frame.loadFinished.connect(onLoad)
Aditionally, for getting more debug information in situations like this, you might want to implement QtWebKit.QWebPage.javaScriptConsoleMessage.
There are at least two errors in the example code.
Firstly, when you add the object to the javascript window, you call it "pyBridge", but you then try to reference it in the javascript as "bridgeObj". Obviously, this will throw a ReferenceError which will prevent any further execution of the script.
Secondly, the doStuff method is missing a self argument, which will cause a TypeError to be raised by PySide.
Dealing with those two issues should be enough to fix your example code, so long as you make sure that the bridge object is added to the javacsript window before the html is loaded. This step is required if you want to reference the bridge object in top-level javascript code. However, if the bridge object is only ever referenced in function-level code, it can be safely added to the javascript window after the html has loaded.

Categories

Resources