Firebase child_removed not working in real-time - angularjs

I am following tutsplus Real time web apps with Angularjs and Firebase.
I have main.js (below) which allows me to add and change items in Firebase in real time with no refresh of the browser (in Chrome and Safari).
However when I delete a message from Firebase I have to refresh the browser for the message list to update - so not in real time. I can't see where the problem is.
/*global Firebase*/
'use strict';
/**
* #ngdoc function
* #name firebaseProjectApp.controller:MainCtrl
* #description
* # MainCtrl
* Controller of the firebaseProjectApp
*/
angular.module('firebaseProjectApp')
.controller('MainCtrl', function ($scope, $timeout) {
var rootRef = new Firebase('https://popping-inferno-9738.firebaseio.com/');
var messagesRef = rootRef.child('messages');
$scope.currentUser=null;
$scope.currentText=null;
$scope.messages=[];
messagesRef.on('child_added', function(snapshot){
$timeout(function() {
var snapshotVal = snapshot.val();
console.log(snapshotVal);
$scope.messages.push({
text: snapshotVal.text,
user: snapshotVal.user,
name: snapshot.key()
});
});
});
messagesRef.on('child_changed', function(snapshot){
$timeout(function() {
var snapshotVal = snapshot.val();
var message = findMessageByName(snapshot.key());
message.text = snapshotVal.text;
});
});
messagesRef.on('child_removed', function(snapshot){
$timeout(function() {
var snapshotVal = snapshot.val();
var message = findMessageByName(snapshot.key());
message.text = snapshotVal.text;
});
});
function deleteMessageByName(name){
for(var i=0; i < $scope.messages.length; i++){
var currentMessage = $scope.messages[i];
if(currentMessage.name === name){
$scope.messages.splice(i, 1);
break;
}
}
}
function findMessageByName(name){
var messageFound = null;
for(var i=0; i < $scope.messages.length; i++){
var currentMessage = $scope.messages[i];
if(currentMessage.name === name){
messageFound = currentMessage;
break;
}
}
return messageFound;
}
$scope.sendMessage = function(){
var newMessage = {
user: $scope.currentUser,
text: $scope.currentText
};
messagesRef.push(newMessage);
};
});

The code that is invoked when a message is deleted from Firebase:
messagesRef.on('child_removed', function(snapshot){
$timeout(function() {
var snapshotVal = snapshot.val();
var message = findMessageByName(snapshot.key());
message.text = snapshotVal.text;
});
});
This code never actually deletes the message from the HTML/DOM.
There is a convenient deleteMessageByName method to handle the deletion. So if you modify the above to this, it'll work:
messagesRef.on('child_removed', function(snapshot){
$timeout(function() {
deleteMessageByName(snapshot.key());
});
});

Related

Two $firebaseArrays on one page & one ctrl

I would like to use two different $firebaseArrays on one view with one controller. But only one of them works and the other only works if i put him in his own controller.
from my factory file:
.factory("AlphaFactory", ["$firebaseArray",
function($firebaseArray) {
var ref = firebase.database().ref('alpha/');
return $firebaseArray(ref);
}
])
.factory("BetaFactory", ["$firebaseArray",
function($firebaseArray) {
var ref = firebase.database().ref('beta/');
return $firebaseArray(ref);
}
])
and my controller:
.controller('DemoCtrl', function($scope, AlphaFactory, BetaFactory) {
$scope.alphaJobs = AlphaFactory;
$scope.addalphaJob = function() {
$scope.alphaJobs.$add({
Testentry: $scope.loremipsum,
timestamp: Date()
});
$scope.alphaJob = "";
};
$scope.betaJobs = BetaFactory;
$scope.addbetaJob = function() {
$scope.betaJobs.$add({
Testentry2: $scope.dolorest,
timestamp: Date()
});
$scope.betaJob = "";
};
)}
Are you sure it is not a simple matter of a promise has not finished?
var alphaJobs = AlphaFactory;
alphaJobs.$loaded().then(function() {
// Do something with data if needed
$scope.alphaJobs = alphaJobs;
});
var betaJobs = BetaFactory;
betaJobs.$loaded().then(function() {
// Do something with data if needed
$scope.betaJobs = betaJobs;
});

Backbone view not removing properly?

There is something I'm missing here it seems my view is not removing.
// ROUTER //
screensaveroff: function() {
AnimationManager.outAnimation([self.screensaverView], function() {
console.log($(this.screensaverView.el).length); //!! always trigger 1 !!
});
}
// ANIMATION MANAGER outANimation function (trigger outAnimation for the passed view as arg)//
outAnimation : function(animationArray, callback){
var time = [];
window.animationArray = animationArray;
for (var i=0; i<animationArray.length; i++)
{
var view = animationArray[i];
view.outAnimation();
time[i] = animationArray[i].animationTime;
}
var timeoutMax = Math.max.apply(null, time);
setTimeout(function(){callback()},timeoutMax);
}
// screensaverView outANimation function //
outAnimation: function() {
var self = this;
this.$el.slideToX(1920, self.animationTime, function() {
self.clearIntervalAnimation();
self.remove();
});
},
any idea what's wrong with my code ?? thanks a lot

Clearing input field on firebase function after angular submit

The function works and submits the user input to my firebase "back-end" but I cannot figure out a clear function to empty out the input field after using ng-submit. The input is tied to the var "emailInput" with ng-model. Thanks for any suggestions!
var newEmailref = new Firebase("https://nevermind.com");
$scope.email = $firebaseArray(newEmailref);
$scope.addEmail = function(email) {
$scope.email.$add(email);
$scope.emailInput = '';
};
I needed to assign a key to the email input and also an empty object.
$scope.emailInput = {};
var newEmailref = new Firebase("https://archerthedog.firebaseio.com/email");
$scope.email = $firebaseArray(newEmailref);
$scope.addEmail = function(email) {
$scope.email.$add(email);
$scope.emailInput = {};
};
See the Full code of mine it's working for me
var ref = firebase.database().ref();
var firebasedata = $firebaseObject(ref);
var messagesRef = ref.child("storeUserData");
var data = $firebaseArray(messagesRef)
$scope.createItem= function(user) {
data.$add(user).then(function(data) {
$scope.user = "";
var myPopup = $ionicPopup.show({
title: 'Dear User, Your Account has created Successfully',
});
$timeout(function() {
myPopup.close(); //close the popup after 6 seconds for some reason
}, 6000);
});
}
ref.orderByValue().on("value", function(data) {
data.forEach(function(takenData) {
console.log("The " + takenData.key + " rating is " +
takenData.val().email);
});
});
Your code just needs a small modification to use $scope.email = ""; instead of $scope.emailInput = '';:
var newEmailref = new Firebase("https://nevermind.com");
$scope.email = $firebaseArray(newEmailref);
$scope.addEmail = function(email) {
$scope.email.$add(email);
$scope.email = '';
};
i didn't get you.... If add a item in firebase database the database will create key value,
if you doing like this
var ref = firebase.database().ref('players/');
ref.orderByValue().on("value", function(data) {
data.forEach(function(takenData) {
console.log("The " + takenData.key + " rating is " +
takenData.val().email);
});
});
The console.log answer will be for takenData.key is some id value like
(-Ko7cGuymlshrS2JQEEC)
Then takenData.val().email) is an email address...

ng-infinite scroll angular setting offset

Need to keep track of my offset so that I can get the next set each time either scroll or click 'Load more'. It improves performance. I am trying out here by setting offset and limit and passing as request params to my node server,but how to update or increment after that limit using offset:
my url as: /foo?limit=7&&offset=0;
My angular controller function as:
$scope.findDetails = function(){
var limit = 10;
var offset = 0;
//DataService.getUsers(limit,offset).then(function(customerdetails){
DataService.getUsers({limit,offset},function(customerdetails){
$scope.customers = customerdetails;
}, function(error){
$scope.status = 'Unable to load customer data: ' + error.message;
});
};
You must keep the offset in the scope of the controller and update the offset every time the infinite directive request more records to display:
$scope.limit = 10;
$scope.offset = 0;
//bind this function to the ng-infinite directive
$scope.infiniteScrollFunction = function() {
$scope.offset += $scope.limit;
$scope.findDetails();
};
$scope.findDetails = function() {
DataService.getUsers({limit: $scope.limit,offset: $scope.offset},
function(customerdetails){
...
}
var $scope.height = $('#div-height').height()
var flag = false;
var $scope.customers = []
$(window).scroll(function() {
if ($(this).scrollTop() > $scope.height-2000) {
if (!flag) {
flag = true;
refreshCustomers();
}
}
});
function refreshCustomers() {
DataService.getCustomers().then(function (data) {
$scope.customers = $scope.customers.concat(data);
setTimeout(function () {
$scope.height = $('#div-height').height();
flag = false
}, 0.1);
});
}
In DataService
factory.getCustomers = function(){
return $http.get(...api......&&limit=7).then(function (results) {
var customers = results.data.customers;
return customers;
});
};
Now after the window is scrolled up to certain height(windowHeight-2000px), the api is called again to get data. The previous data is being concatenated with present data.

how to handle multiple delete and displaying 1 message using delete service in angular JS

When i check all lists in table, and press delete button, A DELETE SERVICE will be called.(Using AngularJS)
Problem is, i am using a loop, and on successful delete and unsuccessful delete, i am getting alert multiple times.(No. of selection times)
And its not working properly, if place it out of loop because its Async Task.
Here is the code,
This is a controller which initiates a service.
$scope.confirmAction = function() {
var costsToDelete = [];
angular.forEach($scope.objects, function(cost) {
if (cost.selected == true) {
costsToDelete.push(cost);
}
});
$scope.deleted = true;
//need to put confirmation dialog here.
//URL: specific to timesheet deletion. it will be prefixed with constant url
var delRequestUrl = URLs.costsUrl + '/';
deleteService.deleteRecord($scope.objects, costsToDelete, delRequestUrl);
};
This is a service.
.service('deleteService', ['dataService', 'Constant.urls', 'Constants','$q','alerts',function(dataService, URLs, Constants, $q, alerts) {
var deleteService = {};
deleteService.deleteRecord = function(records, listOfRecordsToDelete, url) {
while (listOfRecordsToDelete.length > 0) {
var recordToBeDeleted = listOfRecordsToDelete.pop();
var index = listOfRecordsToDelete.indexOf(recordToBeDeleted);
var delRequestUrl = url + recordToBeDeleted.id;
var result = dataService.deleteObject(delRequestUrl);
result.success(function(data) {
Alert('success');
records.splice(index, 1);
});
result.error(function(data, status, headers, config) {
dataService.handleError(status,data);
Alert('error');
});
}
};
return deleteService; }])
I need a result like: Alert should display only once.
If all items are successfully deleted, then success or failure message.
Why dont you just create a boolean bit var status= false;//default value to true inside success callback handler and false inside error callback handler,
so once all calls are complete based on this bit you can alert success or failure
Angular JS Code:
.service('deleteService', ['dataService', 'Constant.urls', 'Constants','$q','alerts',function(dataService, URLs, Constants, $q, alerts) {
var statusBit = false; // status tracker
var deleteService = {};
deleteService.deleteRecord = function(records, listOfRecordsToDelete, url) {
while (listOfRecordsToDelete.length > 0) {
var recordToBeDeleted = listOfRecordsToDelete.pop();
var index = listOfRecordsToDelete.indexOf(recordToBeDeleted);
var delRequestUrl = url + recordToBeDeleted.id;
var result = dataService.deleteObject(delRequestUrl);
result.success(function(data) {
// Alert('success');
statusBit = true;
records.splice(index, 1);
});
result.error(function(data, status, headers, config) {
dataService.handleError(status,data);
//Alert('error');
statusBit = false;
});
if(statusBit){
Alert('success'); //console.log('successfully deleted');
}
else {
Alert('error'); // console.log('error while deleting');
}
};
return deleteService; }])
.service('deleteService', ['dataService', 'Constant.urls', 'Constants','$q','alerts',function(dataService, URLs, Constants, $q, alerts) {
var deleteService = {};
deleteService.deleteRecord = function(records, listOfRecordsToDelete, url) {
var overallResult = true;
while (listOfRecordsToDelete.length > 0) {
var recordToBeDeleted = listOfRecordsToDelete.pop();
var index = listOfRecordsToDelete.indexOf(recordToBeDeleted);
var delRequestUrl = url + recordToBeDeleted.id;
var result = dataService.deleteObject(delRequestUrl);
result.success(function(data) {
records.splice(index, 1);
});
result.error(function(data, status, headers, config) {
dataService.handleError(status,data);
overallResult = false ;
});
}
};
return deleteService; }])

Resources