AngularJS - Write in dynamic Scope Variables - angularjs

I am using AngularJS and the websocket tool https://github.com/gdi2290/angular-websocket to connect to my websocket Server.
No I am trying to write on dynamic Scope Variables, but it doesn't work.
var webfront = ons.bootstrap('webfront', ['onsen', 'ngWebSocket']);
webfront.factory('MyData', function($websocket) {
var dataStream = $websocket('ws://{$smarty.const.IPADRESSE}:8000');
console.log('Warte auf Antwort - Status '+dataStream.readyState);
var data = {};
dataStream.onMessage(function(message) {
try {
var obj = JSON.parse(message.data);
data.cStatus = obj.cStatus;
data.kLeseAdresse = obj.kLeseAdresse;
console.log(data);
} catch(e) {
data.cStatus= '';
}
});
dataStream.onOpen(function(msg) {
console.log("Verbunden - Status "+dataStream.readyState);
});
dataStream.onError(function(event) {
console.log('connection Error', event);
});
return data;
});
webfront.controller('chater', function ($scope, MyData) {
$scope['ng12289'] = MyData;
});
This is my Code. $scope['ng12289'] is working perfect, but if I change ng12289 with dynamic Variable, nothing happens.
Valuename is in MyData.kLeseAdresse
Thanks for helping.

Does $scope.my_dynamic_variable work?

Related

How to mock $window.Notification

I am still learning the ropes when it comes to unit testing with angular. I have an angular service that I use to create HTML5 notifications. Code is similar to the following:
(function() {
'use strict';
angular
.module('blah')
.factory('OffPageNotification', offPageNotificationFactory);
function offPageNotificationFactory($window) {
//Request permission for HTML5 notifications as soon as we can
if($window.Notification && $window.Notification.permission !== 'denied') {
$window.Notification.requestPermission(function (status) { });
}
function OffPageNotification () {
var self = Object.create(OffPageNotification.prototype);
self.visibleNotification = null;
return self;
}
OffPageNotification.prototype.startNotification = function (options) {
var self = this;
self.options = options;
if(self.options.showHtml5Notification && (!self.options.onlyShowIfPageIsHidden || $window.document.hidden)) {
if($window.Notification && $window.Notification.permission !== 'denied') {
self.visibleNotification = new $window.Notification('Notification', {
body: self.options.notificationText,
icon: self.options.notificationIcon
});
}
}
};
.
.
.
return new OffPageNotification();
}
})();
I am attempting to write unit tests for this but am unsure how to mock $window.Notification so it can be used as both a constructor...
self.visibleNotification = new $window.Notification(....)
and also contain properties
if($window.Notification && $window.Notification.permission !== 'denied')
and methods....
$window.Notification.requestPermission(
An example of something I have tried is:
describe('startNotification', function() {
beforeEach(function() {
var mockNotification = function (title, options) {
this.title = title;
this.options = options;
this.requestPermission = sinon.stub();
};
mockNotification.prototype.permission = 'granted';
mockWindow = {
Notification: new mockNotification('blah', {}),
document: {hidden: true}
};
inject(function (_OffPageNotification_) {
OffPageNotification = _OffPageNotification_;
});
});
it('should display a html5 notification if the relevant value is true in the options, and permission has been granted', function(){
var options = {
showHtml5Notification: true,
onlyShowIfPageIsHidden: true
};
OffPageNotification.startNotification(options);
});
});
I get an error saying '$window.Notification is not a constructor' with this setup and I understand why (I am passing in an instantiated version of the mockNotification). But if I set mockWindow.Notification = mockNotification then I get an error when it calls requestPermission since this is undefined.
Any help is appreciated
Notification should be a constructor. And it should have static properties and methods.
All of the relevant properties of mockNotification are instance properties, while they should be static:
function MockNotification() {}
MockNotification.title = title;
MockNotification.options = options;
MockNotification.requestPermission = sinon.stub();
mockWindow = {
Notification: MockNotification,
document: {hidden: true}
};

AngularJS update Service values when connected or disconnected to firebase

I wish to change the icon color when connected or disconnected to the firebase server. I got this far:
HTML
<button class="button button-icon ion-cloud" ng-style="dbConnectedStyle"></button>
Controller
firebaseRef.$loaded().then( function() {
$scope.dbConnectedStyle = {'color': dbConnectStatus.color};
}
Service
.service('dbConnectStatus', function(firebaseRef){
var status = false;
var color = 'transparent';
var connectedRef = firebaseRef.child(".info/connected");
connectedRef.on("value", function(snap) {
status = snap.val();
if (status) {
color = 'lightgrey';
console.log("Connected to DB (" + color + ")" );
} else {
color = 'transparent';
console.log("Disonnected to DB (" + color + ")" );
}
});
return {
'boolean': status,
'color': color
}
})
It change color the first time. But when disconnecting it doesn't change... seems like it's not two-way binding to the service. How do I achieve this?
UPDATE
Tried to do a reference to the Service as an object rather than doing primitives assignments as explained in the good tutorial A Tale of Frankenstein and Binding to Service Values in Angular.js
I changed the code to the following
HTML
<button class="button button-icon ion-cloud"
ng-style="dbConnectionStatus.connectionStyle">
</button>
Service
.service('dbConnectStatus', function(firebaseRef, $rootScope){
this.status = false;
var styles = {
'offlineStyle': {'color': 'red'},
'onlineStyle': {'color': 'lightgrey'}
};
this.connectionStyle = styles.offlineStyle;
firebaseRef.child(".info/connected")
.on("value",
function(snap) {
this.status = snap.val();
if (snap.val()) {
console.log("Connected to DB.");
this.connectionStyle = styles.onlineStyle;
console.log(this.connectionStyle);
} else {
console.log("Disconnected to DB.");
this.connectionStyle = styles.offlineStyle;
console.log(this.connectionStyle);
}
console.log(this.status);
$rootScope.$broadcast('dbConnection:changed');
}
);
})
Controller
$scope.dbConnectionStatus = dbConnectStatus;
$scope.$on('dbConnection:changed', function() {
console.log("'on(...)' called. This is the $scope.dbConnectionStatus.connectionStyle:");
$scope.dbConnectionStatus = dbConnectStatus;
console.log($scope.dbConnectionStatus.connectionStyle);
console.log("This is the dbConnectStatus.connectionStyle:");
console.log(dbConnectStatus.connectionStyle);
});
$rootScope.$watch('dbConnectStatus', function (){
$scope.dbConnectionStatus = dbConnectStatus;
});
//$rootScope.$apply();
I then reloaded the code and got this console message
I then turned off the connection
I then turn on the connection
It is clear to me that the service dbConnectionStatus isn't updated as a global variable in the way that I expected. I was on the assumption that a service is called once when the application is load and that assigning a scope variable to a service (object) is not a call but a reference...
What am I doing wrong?
I worked in a jsFiddle using $emit and $on to handle the status changes inside the service. The main problem is that when going online the angular binding was not working properly so I needed to force an angular cycle with $scope.$apply().
I started working on the first version of your code but made some refactoring. You can find the full code on the jsFiddle but the service and the controller look like the following:
Service
.service('dbConnectStatus', function($rootScope){
var status = false;
var color = 'red';
var self = {
startWatchingConnectionStatus: function(){
var connectedRef = firebase.database().ref().child(".info/connected");
connectedRef.on("value", function(snap) {
console.log(snap.val());
status = snap.val();
if (status) {
color = 'blue';
console.log("Connected to DB (" + color + ")" );
} else {
color = 'red';
console.log("Disonnected to DB (" + color + ")" );
}
$rootScope.$emit('connectionStatus:change', {style: {'color': color}, status: status}});
});
},
getStatus: function(){
return status;
},
getColor: function(){
return color;
}
};
return self;
})
Controller
.controller('HomeCtrl', ['$scope', 'dbConnectStatus', '$rootScope',function($scope, dbConnectStatus, $rootScope) {
dbConnectStatus.startWatchingConnectionStatus();
$rootScope.$on('connectionStatus:change', function currentCityChanged(event, value){
$scope.color = value.style;
//if changed to connected then force the $apply
if(value.status === true){
$scope.$apply();
}
});
}]);
Let me know if there is anything that is still not clear.
Inspired from #adolfosrs great answer I found the following solution to work for me.
Service
.service('dbConnectStatus', function(firebaseRef, $rootScope){
// Initial setup
var styles = {
'offlineStyle': {'color': 'red'},
'onlineStyle': {'color': 'skyeblue'}
};
// Functions to switch status
var offline = function () {
this.boolean = false;
this.style = styles.offlineStyle;
}
var online = function () {
this.boolean = true;
this.style = styles.onlineStyle;
}
var get_status = function(){
return {
boolean: this.boolean,
style: this.style
}
}
// Read the firebase info and update when changed
firebaseRef.child(".info/connected")
.on("value", function(snap) {
if (snap.val()) {
online();
} else {
offline();
}
$rootScope.$emit('dbConnection:changed', get_status() );
});
})
Controller
// Hide it before the status is known.
$scope.dbConnectionStatus = {'color': 'transparent'};
// Getting and reading status changes
$rootScope.$on('dbConnection:changed', function(event, status) {
$scope.dbConnectionStatus = status.style;
$scope.$apply();
});
You should be able to get this working simply by storing the color in an object in the service and referencing it from the controller. e.g.
View
<button class="button button-icon ion-cloud" ng-style="dbStatusService.style"></button>
Controller
$scope.dbStatusService = dbConnectStatus;
Service
.service('dbConnectStatus', function(firebaseRef){
var status = false;
var style = {color: 'transparent'};
var connectedRef = firebaseRef.child(".info/connected");
connectedRef.on("value", function(snap) {
status = snap.val();
if (status) {
style.color = 'lightgrey';
} else {
style.color = 'transparent';
}
});
return {
'boolean': status,
'style': style
}
});

Angularjs $http my second then before first then is done.

I am not sure what I am doing wrong here, but the Report.xls gets downloaded before report.students gets updated.
How can I make it wait for report.students to be updated before Report.xls get downloaded?
Here is my code
`data service function
function getStudentsForExcel() {
var filter = studentFilter;
filter.data.perPage = StudentsModel.data.countTotal;
return $http.post(url + "/summeries", filter.data)
.then(onStudentSummeries)
.catch(onError);
function onStudentSummeries(response) {
return response.data;
}
}`
This function in my controller
`
function tocsv() {
studentData.getStudentsForExcel().then(function(data) {
report.students = data;
}).then(function() {
var blob = new Blob([document.getElementById('tableReport').innerHTML], {
type: "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;charset=utf-8"
});
saveAs(blob, "Report.xls");
});
}`

Uploading images to Firebase with AngularJS

I have a service that handles "episodes": creating, deleting and updating them. It looks like this:
app.service('Episode', ['$firebase', 'FIREBASE_URL', function($firebase, FIREBASE_URL) {
var ref = new Firebase(FIREBASE_URL);
var episodes = $firebase(ref);
return {
all: episodes,
create: function(episode) {
location.reload();
//Add to firebase db
return episodes.$add(episode);
},
delete: function(episodeId) {
location.reload();
return episodes.$remove(episodeId);
},
update: function(episode) {
location.reload();
return episodes.$save(episode);
}
};
}]);
Inside my controller:
app.controller('AdminCtrl', ['$scope', 'Episode', function ($scope, Episode) {
$scope.episodes = Episode.all;
$scope.createEpisode = function(){
Episode.create($scope.episode).then(function(data){
$scope.episode.name = '';
$scope.episode.title = '';
$scope.episode.description = '';
$scope.episode.time = '';
$scope.episode.img = '';
});
};
$scope.deleteEpisode = function(episodeId){
if(confirm('Are you sure you want to delete this episode?') === true) {
Episode.delete(episodeId).then(function(data){
console.log('Episode successfully deleted!');
});
}
};
$scope.updateEpisode = function(episode) {
Episode.update($scope.episode).then(function(data) {
console.log('Episode successfully updated.');
});
};
The only example of uploading images to Firebase from AngularJS I've seen online is this: https://github.com/firebase/firepano
How am I able to incorporate this into an object based addition/update instead of finding it's index/link?

AngularJS local storage - initialize app retrieving local-stored data

I'm pretty new to angular and I'm trying to avoid losing items added on a simple cart application when the user refreshes the page.
I'm using angularLocalStorage (https://github.com/agrublev/angularLocalStorage) but don't know how to retrieve it back the content.
My lines:
var myApp = angular.module('ionicApp', ['ionic','angularLocalStorage']);
myApp.factory('prodottiData', function($http) {
return {
getFooOldSchool: function(callback) {
$http.get('http://192.168.1.128/hongkongapp/?json=get_recent_posts&post_type=product&custom_fields=all').success(callback);
}
}
});
myApp.factory('DataService', function() {
var myCart = new shoppingCart("AngularStore");
return {
cart : myCart
};
});
myApp.controller('MyController', function MyController ($scope, storage, $ionicSideMenuDelegate, prodottiData, DataService, $sce) {
$scope.toggleLeft = function() {
$ionicSideMenuDelegate.$getByHandle('mainMenu').toggleLeft();
};
$scope.toggleMySecondMenuLeft = function() {
$ionicSideMenuDelegate.$getByHandle('mySecondMenu').toggleLeft();
};
//adding menu data to the scope object
prodottiData.getFooOldSchool(function(data) {
$scope.menu = data;
});
//adding the cart to the scope object
$scope.cart = DataService.cart;
$scope.to_trusted = function(html_code) {
return $sce.trustAsHtml(html_code);
}
images = $scope.menu;
$scope.showloader = function(){
$scope.shownImage = this.post.thumbnail_images.full.url;
$scope.itemDesc = this.post.content;
$scope.itemPrice = this.post.custom_fields._price[0];
$scope.productName = this.post.title;
$scope.skuProdotto = this.post.id;
}
});
Now, if I check local storage on the console I can see something is really stored, but I miss the way to re-populate the cart at startup.
Any help would be great!
why not just using browser local storage ?
you can add it to your services.js as a new service and just used that.
var storeService = myAppServices.factory('storeService', function() {
var service =
{
setClientData:function(client_details)
{
window.localStorage.setItem( "client_data", JSON.stringify(client_details) );
client_data = client_details;
},
getClientData:function()
{
if (client_data == null)
{
client_data = JSON.parse(window.localStorage.getItem("client_data"));
}
return client_data;
}
}
var client_data = null;
return service;
});
From the documentation, to retrieve, it's storage.get('key')
So, to check after refresh:
if (storage.get('someKey')){
$scope.retrieved_value = storage.get('someKey');
}else{
// whatever
}
You can use localStorage instead windows.localStorage.
if(typeof(Storage)!=="undefined")
{
// Code for localStorage/sessionStorage.
var hello = "Hello World!!";
localStorage.setItem("hello",hello);
// get string
console.log(localStorage.getItem("hello")); // will return 'Hello World!!'
var me = {name:'abel',age:26,gender:'male'};
localStorage.setItem("user", JSON.stringify(me));
//fetch object
console.log(localStorage.getItem("user")); // will return {"name":"myname","age":99,"gender":"myGender"}
var objetos = JSON.parse(localStorage.getItem("user"));
console.log(objetos.name);
}
else
{
// Sorry! No Web Storage support..
}

Resources