Call FCM factory in a controller to get notification data - angularjs

since last week I'm triying to get notifications from FCM, using Phonegap and AngularJS .
I could do it with cordova-fcm-plugin, so now I would like to get the data from the message, they suggest use this code:
FCMPlugin.onNotification(
function(data){
if(data.wasTapped){
//Notification was received on device tray and tapped by the user.
alert( JSON.stringify(data) );
}else{
//Notification was received in foreground. Maybe the user needs to be notified.
alert( JSON.stringify(data) );
}
},
function(msg){
console.log('onNotification callback successfully registered: ' + msg);
},
function(err){
console.log('Error registering onNotification callback: ' + err);
}
);
My problem was that I have no idea how to added that code to an angular controller, so I searched on internet something similar and I found this factory
angular.module('rhoAppApp')
.factory('$FCMPlugin', $FCMPlugin);
$FCMPlugin.$inject = [];
function $FCMPlugin() {
var service = {
getToken: function(successCallback, failCallback) {
FCMPlugin.getToken(successCallback, failCallback);
},
onNotification: function(onNotification, onCallbackSuccesSet, onCallbackFailSet) {
FCMPlugin.onNotification(onNotification,
onCallbackSuccesSet, onCallbackFailSet);
}
};
return service;
}
So now my problem is use that factory in my controller, I know (maybe I'm wrong) that you have to call it from:
.controller('MainCtrl', function ($FCMPlugin) {
$FCMPlugin.something
})
But I'm not sure how to use that factory, I have never used one before.

I could solve this problem with this:
I made a build using phonegap + yeoman angular, one of the problem building with this method is that you have to include cordova.js
My problema was, that i include condorva.js inside this line
<!-- build:js(.) scripts/vendor.js -->
<!-- bower:js -->
<script src="bower_components/jquery/dist/jquery.js"></script>
<script src="bower_components/angular/angular.js"></script>
<script src="bower_components/bootstrap/dist/js/bootstrap.js"></script>
<!-- endbower -->
<!-- endbuild -->
And it is a problem because you dont want to build it in vendor.js, instead I added cordova.js out of that line:
Then I added this code to app.js to indetify when you are inside of a mobile device or web:
angular.element(document).ready(function () {
if (navigator.userAgent.match(/(iOS|iPhone|iPod|iPad|Android|BlackBerry)/)) {
document.addEventListener('deviceready', function () {
console.log('This is mobile app');
angular.bootstrap(document.body, ['moodleAppApp']);
}, false);
} else {
console.log('This is web app');
angular.bootstrap(document.body, ['moodleAppApp']);
}
});
Also I remove ng-app from index.html
All this make my angular app work with cordova.

Related

Using factory in another factory is undefined - AngularJS

I have a factories called ReportService and IndexService. I want to use IndexService inside of ReportService.
But in ReportService, it says that the IndexService is undefined. I'm not quite sure why.
Here's my code so far:
indexService.js
angular.module('IndexService', []).factory('IndexService', ['$http', function ($http) {
return {
// Sending npm config from server (node) to front-end as JSON so we can use it in front-end.
// See localhost.json.
getConfig: function() {
return $http.get("/api/get-config");
}
}
}]);
reportService.js
angular.module('ReportService', []).factory('ReportService', ['$http', 'IndexService', function ($scope, $http, IndexService) {
// Sending npm config from server (node) to front-end as JSON so we can use it in front-end.
// See localhost.json.
IndexService.getConfig()
.then(function(response) {
var configs = response.data
});
return {
generateExcelReport: function(searchCriteriaList) {
var requestConfig = {
responseType: "arraybuffer",
headers: { "Content-Disposition": "attachment" }
};
// I want to call IndexService.getConfig()
// so I can change my base URL and port based on environment. My configs are in node.js back-end
var url = configs.url;
var port = configs.port;
return $http.post(url + ":" port + "/my-api-link", searchCriteriaList, requestConfig);
},
}
}]);
app.js
angular.module('myApp', ['ngStorage', 'ngRoute', 'appRoutes', 'IndexController', 'IndexService', 'ReportController', 'ReportService', 'PackageController', 'PackageService', 'FarmService', 'DesignService', 'UserService', 'oitozero.ngSweetAlert', 'ui.select', 'ui.materialize', 'ngSanitize', 'ngFileSaver'])
my index.html script imports
<!-- Our Angular Controllers and Services JS -->
<script src="./js/controllers/indexController.js"></script>
<script src="./js/controllers/reportController.js"></script>
<script src="./js/controllers/nerdController.js"></script>
<script src="./js/controllers/packageController.js"></script>
<script src="./js/services/indexService.js"></script>
<script src="./js/services/reportService.js"></script>
<script src="./js/services/farmService.js"></script>
<script src="./js/services/packageService.js"></script>
<script src="./js/services/designService.js"></script>
<script src="./js/services/userService.js"></script>
<script src="./js/appRoutes.js"></script>
<script src="./js/app.js"></script>
Kindly help. I've been over 2 hours on this and I can't still find the problem.. Thanks in advance :)
You need to inject it first, like:
angular
.module('ReportService')
.factory('ReportService', ReportService);
ReportService.$inject = ['IndexService'];
function ReportService(IndexService) {
// You code blah blah here
}
At least this is a way, how i am doing.

Cordova Geofencing plugin not working

I need to make an application which alert on the user when the user enters a particular geofenced area. I tried cordova geofencing plugin. But it doesn't work when I enter the area. I don't know what is the problem. Here are my codes.
app.js
// Ionic Starter App
// angular.module is a global place for creating, registering and retrieving Angular modules
// 'starter' is the name of this angular module example (also set in a <body> attribute in index.html)
// the 2nd parameter is an array of 'requires'
angular.module('starter', ['ionic','ngCordova'])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function () {
// $log.log('Ionic ready');
// Hide the accessory bar by default (remove this to show the accessory bar above the keyboard
// for form inputs)
if ($window.cordova && $window.cordova.plugins.Keyboard) {
cordova.plugins.Keyboard.hideKeyboardAccessoryBar(true);
}
if ($window.StatusBar) {
StatusBar.styleDefault();
}
if ($window.geofence) {
$window.geofence.initialize();
$window.geofence.onTransitionReceived = function (geofences) {
// $log.log(geofences);
if (geofences) {
$rootScope.$apply(function () {
geofences.forEach(function (geo) {
geo.notification = geo.notification || {
title: 'Geofence transition',
text: 'Without notification'
};
// toaster.pop('info', geo.notification.title, geo.notification.text);
});
});
}
};
$window.geofence.onNotificationClicked = function (notificationData) {
$log.log(notificationData);
if (notificationData) {
$rootScope.$apply(function () {
// toaster.pop('warning', 'Notification clicked', notificationData.notification.text);
});
}
};
}
});
})
//Entering Zandig
window.geofence.addOrUpdate({
id: "e941166e-2409-4c97-8c80-14ba9e9d71c9",
latitude: 12.958535143383823,
longitude: 77.6381016522646,
radius: 5,
transitionType: 1
}).then(function () {
document.getElementById("notification").innerHTML= "Reached Zandig";
console.log('Geofence successfully added');
}, function (reason) {
console.log('Adding geofence failed', reason);
});
//Leaving Trivandrum
window.geofence.addOrUpdate({
id: "1e473337-4747-4ac3-b921-ccaf572f38ce",
latitude: 8.487695348115592,
longitude: 76.95057034492493,
radius: 3,
transitionType: 2
}).then(function () {
document.getElementById("notification").innerHTML= "Left Trivandrum";
console.log('Geofence successfully added');
}, function (reason) {
console.log('Adding geofence failed', reason);
});
//Entering 61
window.geofence.addOrUpdate({
id: "8f8119ce-b577-4f22-9880-57333fcff5de",
latitude: 12.9593547,
longitude: 77.63604520000001,
radius: 5,
transitionType: 1
}).then(function () {
document.getElementById("notification").innerHTML= "Entered 61";
console.log('Geofence successfully added');
}, function (reason) {
console.log('Adding geofence failed', reason);
});
//Entering Santhi Sagar
window.geofence.addOrUpdate({
id: "d2c08c58-4f31-44e9-8a5c-8baaae3ebee3",
latitude: 12.960690294723518,
longitude: 77.63856634497643,
radius: 15,
transitionType: 1
}).then(function () {
document.getElementById("notification").innerHTML= "Entered Santhi Sagar";
console.log('Geofence successfully added');
}, function (reason) {
console.log('Adding geofence failed', reason);
});
//Leaving Santhi Sagar
window.geofence.addOrUpdate({
id: "6923cf7d-470e-4921-9b54-4516c504cba5",
latitude: 12.960690294723518,
longitude: 77.63856634497643,
radius: 15,
transitionType: 2
}).then(function () {
document.getElementById("notification").innerHTML= "Left Santhi Sagar";
console.log('Geofence successfully added');
}, function (reason) {
console.log('Adding geofence failed', reason);
});
//Getting watched from device
window.geofence.getWatched().then(function (geofencesJson) {
var geofences = JSON.parse(geofencesJson);
});
//Listening for Geofencing transitions
window.geofence.onTransitionReceived = function (geofences) {
geofences.forEach(function (geo) {
alert('Geofence transition detected');
console.log('Geofence transition detected', geo);
});
};
//When click on notification
window.geofence.onNotificationClicked = function (notificationData) {
Alert('Geofencing is Working');
console.log('App opened from Geo Notification!', notificationData);
};
Index.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<title></title>
<link href="lib/ionic/css/ionic.css" rel="stylesheet">
<link href="css/style.css" rel="stylesheet">
<!-- IF using Sass (run gulp sass first), then uncomment below and remove the CSS includes above
<link href="css/ionic.app.css" rel="stylesheet">
-->
<!-- ionic/angularjs js -->
<script src="lib/ionic/js/ionic.bundle.js"></script>
<!-- cordova script (this will be a 404 during development) -->
<script src="js/ng-cordova.min.js"></script>
<script src="cordova.js"></script>
<!-- your app's js -->
<script src="js/app.js"></script>
</head>
<body ng-app="starter">
<ion-pane>
<ion-header-bar class="bar-stable">
<h1 class="title">Geofencing</h1>
</ion-header-bar>
<ion-content>
<p id="notification"></p>
</ion-content>
</ion-pane>
</body>
</html>
(In the Github page of the plugin, there was an option that 'unique id for geofence'. I added the unique id from UUID generator online page.)
But no alert is displaying. Can anyone help?
When I run using ionic serve, in the console, the following error found. 'Uncaught TypeError: Cannot read property 'addOrUpdate' of undefined'.
Here is my console errors with device.
0 466310 error Uncaught TypeError: Cannot read property'addOrUpdate' of undefined, htttp://192.168.43.148.8100/js/app.js, Line 28
1 466870 error No Content-Security-Policy meta tag found. Please add one when using the cordova-plugin-whitelist plugin.
2 466930 error Uncaught TypeError: object is not a function, http://192.168.43.148:8100/plugins/cordova/plugin-geofence/www.geofence.js, Line 119
Can anyone help me?
Here is a ionic sample project from authors of same plugin : https://github.com/cowbell/ionic-geofence , in it you can see total guide of how to use it in ionic. Your code should also work but you are doing few mistakes.If you want to run some plugin related code at initialization of application, put them into .run() part, you are using plugin calls out of that. Plus no need to use document.addEventListener('deviceready') as you have $ionicPlatform.ready, initialize plugin in that. Your code will be like this
angular.module('starter', ['ionic','ngCordova'])
.run(function($ionicPlatform) {
$ionicPlatform.ready(function() {
//Use your plugin related calls in this area
})
});
You were getting error of undefined because you were making plugin calls before even their object was available to application.Again, any plugin related calls which you want to run at time of initialization, use them in $ionicPlatform.ready(function() {}) .
so I see you said you tested it using ionic server. you cant test plugins via the browser, you have to actually install it on the device in order to test cordova plugins. You can also test most plugins via emulation using the intel xdk. https://software.intel.com/en-us/intel-xdk just import your project and emulate it then move to your geofenced location via the map on the right. Or you can hit the test tab and push it to a phone and test it using the intel app preview app on your iphone or android device. Last but not least you can use the debug tab to push it straight to a device using a usb cable and this will allow you to have a debugging console while you test the plugin on your device.

Angularjs loading Google Api

I'm having an issue using the Google Api in my angularjs 1.3 (SPA using ui.router). Per the google api instructions, I added a reference to the client.js file with a call back in my index.html head,
<html ng-app="myApp">
<head>
<script src="Scripts/jquery-2.1.3.min.js"></script>
<script src="Scripts/angular.min.js"></script>
<script src="Scripts/angular-ui-router.min.js"></script>
<script>
function LoadGAPI() {
}
</script>
<script type="text/javascript" src="https://apis.google.com/js/client.js?onload=LoadGAPI"></script>
As I understand, client.js will asynchronously load the full client api, and when complete call the defined function LoadGAPI.
Sometimes LoadGAPI is called before my angular app .run is called, and sometimes it is not. I don't mind that it loads asynchonously.. but how can I alert my angular app that it is indeed ready for use?
I faced something similar before and there are two ways of solving it, one is delaying the whole angular's bootstrapping till the other library gets loaded by triggering it manually after LoadGAPI and dom ready, something like:
var n = 0;
function LoadGAPI () {
// Only pass after the first call
if (n++) {
angular.bootstrap(angular.element(document).find('html'), ['app']);
}
};
angular.element(document).ready(LoadGAPI);
and the other one is ensuring the library's presence only for the ui-router states needing it using resolve:
State
$stateProvider
...
.state('some.state', {
url : '/some',
templateUrl: 'view/some.state.html',
controller : 'some.state',
resolve : GAPI.resolver
})
...
Resolver
var GAPI = {
ready : false,
resolver: {
api: ['$q', function($q) {
if (!GAPI.deferred) {
GAPI.deferred = $q.defer();
}
if (GAPI.ready) {
GAPI.deferred.resolve();
}
return GAPI.deferred.promise;
}]
}
};
window.LoadGAPI = function () {
GAPI.ready = true;
if (GAPI.deferred) {
GAPI.deferred.resolve();
}
};
The second one can be simplified, but I hope you get the idea.

Setting different UI theme for an angular app

I have started working an app using angularjs which can have have different UI themes.
index.html
<html lang="en" data-ng-app="appConfigurator">
<head>
<title>The title</title>
</head>
<body data-ng-controller="appCtrl">
<div data-ng-view></div>
</body>
<script type="text/javascript" src="libs/angular.js"></script>
<script type="text/javascript" src="libs/angular-route.js"></script>
<script type="text/javascript" src="js/app.js"></script>
<script type="text/javascript" src="js/services/webservice.js"></script>
<script type="text/javascript" src="js/controllers/appCtrl.js"></script>
<script type="text/javascript" src="js/router.js"></script>
</html>
app.js - Here I initialize my module and also declare a global variable 'theme'.
var appConfigurator = angular.module("appConfigurator", ['ngRoute']);
var theme = "";
webservice.js - This service make Web service calls to the backend and gets the data as response.
appConfigurator.factory('webService', function($http) {
return {
callService : function(method, fileType, rowId, data, message, type) {
return $http({
method : method,
url : url,
data : "Message=" + message + "&XMLData=" + data + "&Type=" + type,
headers : {
'Content-Type' : 'application/x-www-form-urlencoded'
}
});
}
};
});
appCtrl.js - This is the main app controller. Here I am making a webservice call to get the data and then using this data I will have to make one more call to get the name of the "theme" I need to use. So basically two calls.
appConfigurator.controller("appCtrl", function($scope, webService) {
$scope.succ = function(res) {
//alert("success" + res.name);
};
$scope.err = function(res) {
alert("error");
}
webService.callService('POST', 'data', 'ID', '', 'Message','XML').success($scope.succ).error($scope.err);
});
router.js - Based on the value of theme the route will route to the particular folder structure which will contain the theme specific HTML, CSS and JS files.
appConfigurator.config(['$routeProvider', function($routeProvider) {
$routeProvider.when('/Config', {
templateUrl: 'themes/'+theme+'/views/a.tmpl.html',
controller: ''
}).otherwise({
redirectTo: '/Config'
});
}
]);
The obvious problem is that by the time routers sets the path for the tempelateUrl I don't have the name of the theme.
Solutions -
1) One solution (this one works) is to get the theme name in the URL as a parameter but that cannot be done on the backend side. So there is no point of this solution.
2) Is there a way I can delay the routing process so that by the time angular tries to route I have the theme name.
The development is in very initial stage. Comments to change the approach will also be helpful. And yes Angularjs is all new to me and my peers.
appConfigurator.config(['$routeProvider', function($routeProvider) {
// set theme name
var theme = 'theme_name';
$routeProvider.when('/Config', {
templateUrl: 'themes/'+theme+'/views/a.tmpl.html',
controller: ''
}).otherwise({
redirectTo: '/Config'
});
}
]);

ServiceStack MiniProfiler Ajax Requests Logging

So, in my Index.cshtml page, when I initially load up the page I have:
#inherits ViewPage
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="ext-all-debug.js"></script>
<script type="text/javascript" src="app.js"></script>
<script type="text/javascript" src="app.ext.js"></script>
<script type="text/javascript" src="dump.js"></script>
#ServiceStack.MiniProfiler.Profiler.RenderIncludes().AsRaw()
</head>
<body>
</body>
</html>
All good, I can see it profiling index, a bunch of ExtJS, and the 1st ajax call to my ServiceStack on server side (in /api/session).
Now, in my ExtJS form I have a Customers tab when I click it sends ajax request to /api/customers and I have a tab when I click it calls /api/orders.
But, then when I start to click on, say Customers tab, Miniprofiler does not add any subsequent ajax requests into the list any more? I thought Miniprofiler can log ajax requests nothing special needs to be done? Why is it not logging subsequent ajax requests for me? I am missing something?
I know this is a little bit old, but if anyone is interested the implementation for using miniprofiler with angularjs is as follows:
app.config(['$httpProvider', function ($httpProvider) {
$httpProvider.interceptors.push(["$q", function ($q) {
return {
'response': function (response) {
if (typeof (MiniProfiler) != 'undefined' && response.config.url.indexOf(".html") < 0) {
var stringIds = response.headers('X-MiniProfiler-Ids');
if (stringIds) {
MiniProfiler.fetchResultsExposed(angular.fromJson(stringIds));
}
}
return response || $q.when(response);
}
};
}]);
}]);
The current version available through Nuget doesn't support intercepting ExtJS ajax calls.
It seems that there is a pull request for that feature, but it isn't available yet.
Here's what I had to do to get around that:
Ext.require('Ext.Ajax');
Ext.onReady(function () {
Ext.Ajax.on('requestcomplete', function (e, xhr, settings) {
if (typeof (MiniProfiler) != 'undefined') {
var stringIds = xhr.getResponseHeader('X-MiniProfiler-Ids');
if (stringIds) {
var ids = typeof JSON != 'undefined' ? JSON.parse(stringIds) : eval(stringIds);
MiniProfiler.fetchResultsExposed(ids);
}
}
});
});

Resources