Flutter webview with custom javascriptInterfaceAdapter or invoke JS using webview controller - javascript

I have an old java project that performs in andorid webview with addJavascriptInterface
mWebView.addJavascriptInterface(new JavascriptAdapter(), "AndroidFunctions");
Within JavascriptAdapter class there is several #JavascriptInterface functions. as example
class JavascriptAdapter {
#JavascriptInterface
getMacAddress(){
DeviceInfo deviceInfo = new DeviceInfo(activity);
return deviceInfo.getMacAddress();
}
}
now after opening the webview within android applications, using JS we can access that function like this way -
var strMacAddress = AndroidFunctions.getMACAddress();
Now I would like to achieve this thing on flutter. for that, I am using the flutter inAppWebview plugin.
also, I have tried flutter_webview, WKWebview.

Please take a look in this documentation for InAppWebView.
JavScriptInterface are normally used to call native methods from webview. I am assuming that the webpage calls the method, so, you have to return the Mac Address as it is presented in the documentation. But you need to change the way for calling the method for flutter by adding this sample(provided in documentation) to you webpage source.
<script>
window.addEventListener("flutterInAppWebViewPlatformReady", function(event) {
window.flutter_inappwebview.callHandler('handlerFoo')
.then(function(result) {
// print to the console the data coming
// from the Flutter side.
console.log(JSON.stringify(result));
window.flutter_inappwebview
.callHandler('handlerFooWithArgs', 1, true, ['bar', 5], {foo: 'baz'}, result);
});
});
</script>

You can inspect this Webview from google chrome.
chrome://inspect/#devices
and don't forget to add flutter_inappwebview: ^5.3.2 in your pubspec.yaml
the answer is already given in this link
I have just added for a quick look on SO.
import 'dart:async';
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
if (Platform.isAndroid) {
await AndroidInAppWebViewController.setWebContentsDebuggingEnabled(true);
}
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
InAppWebViewGroupOptions options = InAppWebViewGroupOptions(
android: AndroidInAppWebViewOptions(
useHybridComposition: true,
),);
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(title: Text("JavaScript Handlers")),
body: SafeArea(
child: Column(children: <Widget>[
Expanded(
child: InAppWebView(
initialData: InAppWebViewInitialData(
data: """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
</head>
<body>
<h1>JavaScript Handlers</h1>
<script>
window.addEventListener("flutterInAppWebViewPlatformReady", function(event) {
window.flutter_inappwebview.callHandler('handlerFoo')
.then(function(result) {
// print to the console the data coming
// from the Flutter side.
console.log(JSON.stringify(result));
window.flutter_inappwebview
.callHandler('handlerFooWithArgs', 1, true, ['bar', 5], {foo: 'baz'}, result);
});
});
</script>
</body>
</html>
"""
),
initialOptions: options,
onWebViewCreated: (controller) {
controller.addJavaScriptHandler(handlerName: 'handlerFoo', callback: (args) {
// return data to the JavaScript side!
return {
'bar': 'bar_value', 'baz': 'baz_value'
};
});
controller.addJavaScriptHandler(handlerName: 'handlerFooWithArgs', callback: (args) {
print(args);
// it will print: [1, true, [bar, 5], {foo: baz}, {bar: bar_value, baz: baz_value}]
});
},
onConsoleMessage: (controller, consoleMessage) {
print(consoleMessage);
// it will print: {message: {"bar":"bar_value","baz":"baz_value"}, messageLevel: 1}
},
),
),
]))),
);
}
}

Related

Use js file inside the html file Flutter

How can I use a js file associated with an html in Flutter. I use the webview_flutter plug-in to load the index.html file and it works, but I am not able to load the js file
This is my Flutter code:
return Scaffold(
appBar: AppBar(
title: Text(widget.title),
),
body: WebView(
initialUrl: '',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
_webViewController = webViewController;
_loadHtmlFromAssets();
},
),
_loadHtmlFromAssets() async {
String fileHtmlContents = await rootBundle.loadString('files/index.html');
_webViewController.loadUrl(Uri.dataFromString(fileHtmlContents, mimeType: 'text/html', encoding: Encoding.getByName('utf-8')).toString());
}
And this is my html file
<!DOCTYPE html>
<html>
<head>
<meta charset="UTF-8">
<script type="text/javascript" **src="files/plotter.js**"></script>
<title>Test plotter</title>
</head>
<body>
<!-- <script type="text/javascript" src="plotter.js"></script> -->
<div id='test'></div>
<script type="text/javascript">
This is the message that appears in conosle
I/chromium(31201): [INFO:CONSOLE(86)] "Uncaught ReferenceError: Plotter is not defined", source: data:text/html;charset=utf-8,%
Instead of reading the asset and then loading from data uri, just pass the asset path like this:
_loadHtmlFromAssets() async {
_webViewController.loadUrl('file:///android_asset/flutter_assets/files/index.html');
}
And in index.html file, the script path should be relative. For me index.html and index.js were in same path so this works:
<script src="index.js"></script>
And my pubspec.yml looks like this:
assets:
- files/index.html
- files/index.js
Edit
Platform independent solution using local_assets_server:
import 'dart:io';
import 'package:flutter/material.dart';
import 'package:local_assets_server/local_assets_server.dart';
import 'package:webview_flutter/webview_flutter.dart';
void main() => runApp(MyApp());
class MyApp extends StatelessWidget {
// This widget is the root of your application.
#override
Widget build(BuildContext context) => MaterialApp(home: MyWidget());
}
class MyWidget extends StatefulWidget {
#override
_MyWidgetState createState() => _MyWidgetState();
}
class _MyWidgetState extends State<MyWidget> {
String address;
int port;
bool isListening = false;
#override
initState() {
_initServer();
super.initState();
}
_initServer() async {
final server = new LocalAssetsServer(
address: InternetAddress.loopbackIPv4,
assetsBasePath: 'files',
);
final address = await server.serve();
setState(() {
this.address = address.address;
port = server.boundPort;
isListening = true;
});
}
List<String> propList = [];
#override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('My WebView'),
),
body: !isListening ? Center(child: CircularProgressIndicator()) : WebView(
initialUrl: 'http://$address:$port',
javascriptMode: JavascriptMode.unrestricted,
onWebViewCreated: (WebViewController webViewController) {
}),
);
}
}
And for android, add usesCleartextTraffic="true" in manifest file:
<application
....
android:usesCleartextTraffic="true"

Flutter Webview two way communication with Javascript

I have an html file that I am loading in Flutter webview using flutter_webview_plugin. I am using evalJavascript to call function in my javascript code, meaning flutter(dart)->js. However, I also need some way to communicate back something to flutter(dart) layer, meaning js->flutter(dart).
I have tried using
- webkit.messageHandlers.native
- window.native
to support both platforms(Android,iOS) checking if those are available in JS. But, those comes as undefined. Using following code to get instance of native handler in JS.
typeof webkit !== 'undefined' ? webkit.messageHandlers.native :
window.native;
And even if I get that instance and post message using it, not sure how to handle it in flutter(dart) layer. I may need to use platform channels. Not sure, if I am in the right direction.
Is there any way through which I can do that? I have evaluated interactive_webview plugin. It works fine on Android. But, it has swift versioning issue and don't want to proceed further with that.
Any help would be appreciated.
Here is an example of communication from Javascript code to flutter.
In Flutter build your WebView like :
WebView(
initialUrl: url,
javascriptMode: JavascriptMode.unrestricted,
javascriptChannels: Set.from([
JavascriptChannel(
name: 'Print',
onMessageReceived: (JavascriptMessage message) {
//This is where you receive message from
//javascript code and handle in Flutter/Dart
//like here, the message is just being printed
//in Run/LogCat window of android studio
print(message.message);
})
]),
onWebViewCreated: (WebViewController w) {
webViewController = w;
},
)
and in Your HTMLfile:
<script type='text/javascript'>
Print.postMessage('Hello World being called from Javascript code');
</script>
When you run this code, you shall be able to see log "Hello World being called from Javascript code" in the LogCat/Run window of android studio.
You can try my plugin flutter_inappbrowser (EDIT: it has been renamed to flutter_inappwebview) and use addJavaScriptHandler({#required String handlerName, #required JavaScriptHandlerCallback callback}) method (see more here).
An example is presented below.
On Flutter side:
...
child: InAppWebView(
initialFile: "assets/index.html",
initialHeaders: {},
initialOptions: InAppWebViewWidgetOptions(
inAppWebViewOptions: InAppWebViewOptions(
debuggingEnabled: true,
)
),
onWebViewCreated: (InAppWebViewController controller) {
webView = controller;
controller.addJavaScriptHandler(handlerName: "mySum", callback: (args) {
// Here you receive all the arguments from the JavaScript side
// that is a List<dynamic>
print("From the JavaScript side:");
print(args);
return args.reduce((curr, next) => curr + next);
});
},
onLoadStart: (InAppWebViewController controller, String url) {
},
onLoadStop: (InAppWebViewController controller, String url) {
},
onConsoleMessage: (InAppWebViewController controller, ConsoleMessage consoleMessage) {
print("console message: ${consoleMessage.message}");
},
),
...
On JavaScript side (for example a local file assets/index.html inside the assets folder):
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Flutter InAppBrowser</title>
...
</head>
<body>
...
<script>
// In order to call window.flutter_inappwebview.callHandler(handlerName <String>, ...args)
// properly, you need to wait and listen the JavaScript event flutterInAppWebViewPlatformReady.
// This event will be dispatched as soon as the platform (Android or iOS) is ready to handle the callHandler method.
window.addEventListener("flutterInAppWebViewPlatformReady", function(event) {
// call flutter handler with name 'mySum' and pass one or more arguments
window.flutter_inappwebview.callHandler('mySum', 12, 2, 50).then(function(result) {
// get result from Flutter side. It will be the number 64.
console.log(result);
});
});
</script>
</body>
</html>
On Android Studio logs you will get:
I/flutter (20436): From JavaScript side:
I/flutter (20436): [12, 2, 50]
I/flutter (20436): console message: 64
I want to tell you about how to send messages from flutter WebView to JS:
In JS code you need to bind your function you need to fire to window
const function = () => alert('hello from JS');
window.function = function;
In your code in WebView widget implementation you need to declare onWebViewCreated method like this
WebView(
onWebViewCreated: (WebViewController controller) {},
initialUrl: 'https://url.com',
javascriptMode: JavascriptMode.unrestricted,
)
In class widget declare var _webViewController;
class App extends State<MyApp> {
final _webViewController;
}
In onWebViewCreated write this code
onWebViewCreated: (WebViewController controller) {
_webViewController = controller;
},
Then you can run code like this:
class App extends StatelessWidget {
var _webViewController;
#override
Widget build(BuildContext context) {
return MaterialApp(
title: 'Flutter Demo',
home: Scaffold(
body: WebView(
onWebViewCreated: (WebViewController controller) {
_webViewController = controller;
},
initialUrl: 'https://url.com',
javascriptMode: JavascriptMode.unrestricted,
),
floatingActionButton: FloatingActionButton(
onPressed: () {
// When you click at this button youll run js code and youll see alert
_webViewController
.evaluateJavascript('window.function ()');
},
child: Icon(Icons.add),
backgroundColor: Colors.green,
),
),
);
}
}
But what if we want to share this _webViewController instance to other widgets like drawer?
In this case I decided to implement Singleton pattern and store _webViewController instance in it.
So
Singleton class
class Singleton {
WebViewController webViewController;
static final Singleton _singleton = new Singleton._internal();
static Singleton get instance => _singleton;
factory Singleton(WebViewController webViewController) {
_singleton.webViewController = webViewController;
return _singleton;
}
Singleton._internal();
}
Then
onWebViewCreated: (WebViewController controller) {
var singleton = new Singleton(controller);
},
And finally in our Drawer widget i.e. (here you can use whatever widget you want)
class EndDrawer extends StatelessWidget {
final singleton = Singleton.instance;
#override
Widget build(BuildContext context) {
return Drawer(
child: Column(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
SizedBox(
width: 200,
child: FlatButton(
onPressed: () {
singleton.webViewController.evaluateJavascript('window.function()');
Navigator.pop(context); // exit drawer
},
child: Row(
children: <Widget>[
Icon(
Icons.exit_to_app,
color: Colors.redAccent,
),
SizedBox(
width: 30,
),
Text(
'Exit',
style: TextStyle(color: Colors.blueAccent, fontSize: 20),
),
],
),
)),
],
),
);
}
}
If you want to receive messages from JS code to your flutter App you need:
In your js code
window.CHANNEL_NAME.postMessage('Hello from JS');
In your flutter code.
When you're running JavascriptChannel(name: 'CHANNEL_NAME', ...)
flutter bind to your window WebView new MessageChannel with name you wrote in constructor (in this case CHANNEL_NAME)
so when we call window.CHANNEL_NAME.postMessage('Hello from JS'); we recieve a message we sent
WebView(
javascriptChannels: [
JavascriptChannel(name: 'CHANNEL_NAME', onMessageReceived: (message) {
print(message.message);
})
].toSet(),
initialUrl: 'https://url.com',
)
So here we are.
I'm new in flutter code
So if you have another better experience about this you can write in comments to help other people!
Full code example of Javascript callbacks using package flutter_inappwebview:
import 'dart:async';
import 'package:flutter/material.dart';
import 'package:flutter_inappwebview/flutter_inappwebview.dart';
Future main() async {
WidgetsFlutterBinding.ensureInitialized();
runApp(new MyApp());
}
class MyApp extends StatefulWidget {
#override
_MyAppState createState() => new _MyAppState();
}
class _MyAppState extends State<MyApp> {
InAppWebViewController _webViewController;
#override
Widget build(BuildContext context) {
return MaterialApp(
home: Scaffold(
appBar: AppBar(
title: const Text('InAppWebView Example'),
),
body: Container(
child: Column(children: <Widget>[
Expanded(
child: InAppWebView(
initialData: InAppWebViewInitialData(data: """
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
</head>
<body>
<h1>JavaScript Handlers (Channels) TEST</h1>
<button id='test' onclick="window.flutter_inappwebview.callHandler('testFunc');">Test</button>
<button id='testargs' onclick="window.flutter_inappwebview.callHandler('testFuncArgs', 1);">Test with Args</button>
<button id='testreturn' onclick="window.flutter_inappwebview.callHandler('testFuncReturn').then(function(result) { alert(result);});">Test Return</button>
</body>
</html>
"""),
initialOptions: InAppWebViewGroupOptions(
crossPlatform: InAppWebViewOptions(
debuggingEnabled: true,
)),
onWebViewCreated: (InAppWebViewController controller) {
_webViewController = controller;
_webViewController.addJavaScriptHandler(
handlerName: 'testFunc',
callback: (args) {
print(args);
});
_webViewController.addJavaScriptHandler(
handlerName: 'testFuncArgs',
callback: (args) {
print(args);
});
_webViewController.addJavaScriptHandler(
handlerName: 'testFuncReturn',
callback: (args) {
print(args);
return '2';
});
},
onConsoleMessage: (controller, consoleMessage) {
print(consoleMessage);
},
),
),
])),
),
);
}
}
There are two ways to communicate the answer:
First way From Flutter to the webview (javascript, react...)
From the flutter side (using a button or in a trigger method):
webViewController.evaluateJavascript('fromFlutter("pop")');
This fromFlutter will be the name of the method in your javascript, react, whatever and also you can send text, in this case "pop".
From the javascript side inside the html, in your body label:
<script type="text/javascript">
function fromFlutter(data) {
// Do something
console.log("This is working now!!!");
}
</script>
Second way From your webview (javascript, react...) to Flutter
In your Webview attribute javascriptChannels you can add:
javascriptChannels: Set.from([
JavascriptChannel(
name: 'comunicationname',
onMessageReceived: (JavascriptMessage message) async {
// Here you can take message.message and use
// your string from webview
},
)
]),
From the webview using the same communication name "communicationname" (your can use another name in both places):
window.communicationname.postMessage("native,,,pop,");
Flutter 3.0.5
webview_flutter: ^3.0.4
flutter_js: ^0.5.0+6
Another way to use JavascriptChannels is to tranfer data from the "App" to your Website.
Dart:
JavascriptChannel(
name: 'getFCMToken',
onMessageReceived: (JavascriptMessage message) async {
//print(message.message);
final token = (await FirebaseMessaging.instance.getToken())!;
final script = "var appToken =\"${token }\"";
_webViewController.runJavascript(script);
},
),
html:
<script type = "text/javascript">
window.onload = getFCMToken.postMessage('');
</script>
or Dart(Trigger):
OnPageFinished: (url) async {
try {
final token = (await FirebaseMessaging.instance.getToken())!;
var javascript = "var appToken=\"${token.toString()}\"";
} catch (_) {}
}
so in your website code you have a js var "appToken" wich you can use in PHP or whatever.
If you are using webviewx plugin which support web,ios and android than this is how we can do two way communication.
I have webpage which has index.html and other js,and css pages which I want to display in webview and communicate between flutter and web app.
1. From flutter to js listener
IconButton(
icon: Icon(Icons.developer_mode),
onPressed: () {
webviewController
.evalRawJavascript('window.myFunction()',
inGlobalContext: false)
.then((value) => print(value));
},
)
Note: myFunction is function defined in javascript or html page as below.
function myFunction() {
alert("I am an alert box!");
return 'working';
}
2. From js/html to flutter listener
In html/js add button with listener
function submitClick() {
var data = document.getElementById('data').value;
SubmitCallback(data) //defined in flutter
}
Now In flutter(add dartCallback):
WebViewX(
javascriptMode: JavascriptMode.unrestricted,
initialContent: '<h2> Loading </h2>',
initialSourceType: SourceType.HTML,
onWebViewCreated: (controller) {
webviewController = controller;
_loadHtmlFromAssets();
webviewController.addListener(() {});
},
dartCallBacks: {
DartCallback(
name: 'SubmitCallback',
callBack: (msg) {
ScaffoldMessenger.of(context).showSnackBar(
SnackBar(content: Text('Submitted $msg successfully')));
},
),
},
)
PS. Happy Coding

VueJS : Adding to existing HTML and handling imports

So I built a Single Page Application in VueJS which works nicely but the SEO sucks as expected, so I decided to make a normal HTML site with some pages having VueJS code (Remote hosting so no node else I would go SSR).
I followed this guide which works fin
I have a search.js which contains my VueJS instance and methods etc
Vue.component('todo-component', {
template: '#todo-component',
data: function () {
return {
items: [
{
id: 'item-1',
title: 'Checkout vue',
completed: false
}, {
id: 'item-2',
title: 'Use this stuff!!',
completed: false
}
],
newItem: ''
};
},
methods: {
addItem: function () {
if (this.newItem) {
var item = {
id: Math.random(0, 10000),
title: this.newItem,
completed: false
};
this.items.push(item);
this.newItem = '';
}
}
}
});
var app = new Vue({
el: '#vue-app'
});
However, I need to import stuff like axios and other components
if I add an import statement to the script above, it comes up with
import axios from "axios";
Uncaught SyntaxError: Unexpected identifier
Where should my imports go?
Since you are directly writing code running in the browser, you can simply include the axios cdn in your html code before search.js is loaded:
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
As for components import, you can read more about component registration here. Generally if your components are registered globally via Vue.component('my-component', {}) syntax, you should be able to directly use it within your code.
You're missing axios library so add it as follow :
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
i'm also providing you of how to use it when you work with browser :
new Vue({
el: '#app',
data: {
dataReceived: '',
},
methods: {
getData() {
axios.get('https://min-api.cryptocompare.com/data/price?fsym=BTC&tsyms=USD')
.then((response) => {
this.dataReceived = response.data;
console.log(this.dataReceived);
return this.dataReceived;
})
}
}
})
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title></title>
<script src="https://unpkg.com/vue#2.5.17/dist/vue.js"></script>
<script src="https://unpkg.com/axios/dist/axios.min.js"></script>
</head>
<body>
<div id="app">
<button #click="getData" type="button">getData</button>
<p>dataReceived: {{ dataReceived }}</p>
</div>
</body>

Pusher notification with Laravel 5.4 not working as expected

So I'm really stuck for a while now, with Laravel event and pusher API.
I created event and broadcast, but when I access with pusher Javascript API it returns empty array, when I try to print it in the route it also returns empty array, meanwhile if I check Laravel log stoarage/logs/laravel.log I see exactly what I am expecting in the Javascript and route.
My code:
.env
BROADCAST_DRIVER=pusher
PUSHER_APP_ID=******
PUSHER_APP_KEY=524**************8
PUSHER_APP_SECRET=d2**************c
Boadcasting.php
'default' => env('BROADCAST_DRIVER', 'pusher'),
'connections' => [
'pusher' => [
'driver' => 'pusher',
'key' => env('PUSHER_APP_KEY'),
'secret' => env('PUSHER_APP_SECRET'),
'app_id' => env('PUSHER_APP_ID'),
'options' => [
'cluster' => 'us2',
'encrypted' => true
],
],
The event class: ProjectEvent.php
<?php
namespace App\Events;
use Illuminate\Broadcasting\Channel;
use Illuminate\Queue\SerializesModels;
use Illuminate\Broadcasting\PrivateChannel;
use Illuminate\Broadcasting\PresenceChannel;
use Illuminate\Foundation\Events\Dispatchable;
use Illuminate\Broadcasting\InteractsWithSockets;
use Illuminate\Contracts\Broadcasting\ShouldBroadcast;
class ProjectEvent implements ShouldBroadcast
{
use Dispatchable, InteractsWithSockets, SerializesModels;
public $username;
public $message;
/**
* Create a new event instance.
*
* #return void
*/
public function __construct($username)
{
$this->username = $username;
$this->message = "{$username} sent you a message";
}
/**
* Get the channels the event should broadcast on.
*
* #return Channel|array
*/
public function broadcastOn()
{
return ['project-update'];
}
}
Route:
Route::get('/test', function () {
print_r(event(new App\Events\ProjectEvent('Michel')));
//return "Event has been sent!";
});
Route::get('/view', function () {
return view('testevent');
});
testevent.blade.php
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
<script src="http://js.pusher.com/3.1/pusher.min.js"></script>
<script type="text/javascript">
Pusher.logToConsole = true;
var pusher = new Pusher('524************8', {
cluster: 'us2',
encrypted: true
});
var channel = pusher.subscribe('project-update');
channel.bind('App\\Events\\ProjectEvent', function(data) {
alert(data.message);
});
</script>
</body>
</html>
I really can't figure out where it all going wrong, since I am able to see the event in the log while the JS alert isn't working, also I try to dump the event on the route, it return empty array()

Access external script in meteor blaze Template.events

I have this in my client/templates/main.html:
<head>
<title>app boil</title>
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<script src="https://cdnjs.cloudflare.com/ajax/libs/quickblox/2.4.0/quickblox.min.js"></script>
</head>
So I am calling the quickblox api. This provides a QB object.
I have now client/templates/quickblox/quickbloxcall.js which has this code:
import { Template } from 'meteor/templating';
import './quickbloxcall.html'
Template.quickbloxcall.onRendered(function () {
console.log(QB.createSession);
});
Template.quickbloxcall.events({
'submit .quickblox-form'(event) {
var user = {
id: 4448514,
name: 'chatuserweb1',
login: 'chatuserweb1',
pass: 'chatuserweb1'
};
QB.createSession({login: user.login, password: user.pass}, function(err, res) {
if (res) {
QB.chat.connect({userId: user.id, password: user.pass}, function(err, roster) {
if (err) {
console.log(err);
} else {
/*
* (Object) roster - The user contact list
* roster = {
* '1126541': {subscription: 'both', ask: null}, // you and user with ID 1126541 subscribed to each other.
* '1126542': {subscription: 'none', ask: null}, // you don't have subscription but user maybe has
* '1126543': {subscription: 'none', ask: 'subscribe'}, // you haven't had subscription earlier but now you asked for it
* };
*/
}
});
}else{
console.log(err);
}
});
},
});
In above code, when I submit form, I get this error in console:
Uncaught TypeError: Cannot read property 'createSession' of undefined(…)
So this means that the QB object is not accessible inside Template.quickblox.events submit event handler.
However in console.log() I get this:
function (params, callback) {
this.auth.createSession(params, callback);
}
So this means that the Template.quickbloxcall.onRendered is properly loading the QB object.
How do I access this external script in Template.quickblox.events?
What you're seeing on the console does confirm that QB.createSession exists. But see that within that createSession call is a call to another createSession!
That is, I think you'll find that this.auth inside Qb.createSession is the object that's undefined, and the unavailable createSession belongs to auth (undefined), not QB (defined).
This will happen if you haven't run QB.init before calling QB.createSession. init is explained a bit in the QuickBlox JavaScript SDK docs here.

Categories

Resources