Managing an Array of Likes in AngularJS Service - javascript

I have a like Button on Profile Page, On click of Like Button i want to maintain an array of like and store it into my db.
in profile Controller I have
$scope.likeProfile = UserService.likeProfile(loggedInUser,$state.params.userId);
In User Service I have
function likeProfile(likedBy,id){
var likeArray = [];
likeArray.push(likedBy);
ref.child("users").child(id).update({ likedBy: likeArray});
}
I just want to understand how I could not intialize likeArray everyTime LikeProfile Method is called. So that all likes are pushed into array.

I would do it like this, not sure though if this is what you want to achieve. Initialization should not be done within the function if you want to keep the result. This keeps the result within the scope of one user.
$scope.likeArray = [];
function likeProfile (likedBy, id) {
$scope.likeArray.push(likedBy);
ref.child("users").child(id).update({ likedBy: likeArray});
}
Otherwise, if you need overall likes you have to initialize the array with the previous values within the function, sth. like
likeArray = getLikesFromDB(); // however you access your db
likeArray.push(likedBy);
ref.child("users").child(id).update({ likedBy: likeArray });
Try to debug with the browser dev tools (e.g. in Chrome Tools > Developer Tools) and see what you send in the network tab. If your array only contains one value the whole array will be overwritten unless you write a custom update function that adds a value rather than replaces the value.

Related

Storing a HTML OBJECT Array inside Chrome Storage for a Chrome Extension

BACKGROUND:
I'm writing a chrome extension that when you access a certain page it finds all the table rows and then stores them and when you go back it shows you all the new values that have been added.
I want to store an array in storage so that when the user comes back to the page I can access it. Mainly to compare results each time to see if anything has changed.
Example.
myArray = [HTML OBJECT, HTML OBJECT, HTML OBJECT];
on.window.unload {
Chrome.storage.set(STORE MY ARRAY)
}
on.windows.onload {
chrome.storage.get(MY STORED ARRAY AND SET TO OLD_myArray[])
}
function compareArrays() {
TO DO STUFF WITH MY myArray[] and OLD_myArray[]
e.g. comparing values to see if anything has changed.
}
I've tried local Storage but realised that It doesn't store arrays, So moved to Chrome storage.
I would like help getting myArray to store itself on unload and then set itself to OLD_myArray onload, So I can compare the values for the differences. Thanks.
In order to use chrome.storage, you need to use one of two methods:
chrome.storage.sync, which syncs saved data to any browser the user logs into.
chrome.storage.local, which only saves data to the current machine.
As the official documentation discusses, chrome.storage is implemented with callbacks, not with a return value from the get or set call itself.
// Save the current myArray value.
chrome.storage.local.set({'storedArray': myArray}, function() {
console.log(`storedArray now contains ${myArray}.`);
});
// Retrieve the the stored value, defaulting to an empty array.
chrome.storage.local.get({'storedArray': []}, function(data) {
console.log(`storedArray's value is ${data.storedArray}.`);
});
As an aside, it may not be a great idea to attach storage functions to an unload event, as the browsing context could terminate before the operation is complete. A browser crash, for instance, wouldn't call the window.unload event (this is only one of a number of situations which would interfere with your handler).

trying to fix the problems arising from asynchronous code in javascript

I am new in database systems and what I am trying to do is to check whether the e-mail entered by the user during login exists in the database or not. I use Firebase Databse. So, the code I have written is this:
function login(){
var e_mail = document.getElementById("e-mail").value;
rootRef = firebase.database().ref();
rootRef.orderByChild("E_mail").on("child_added", function(snapshot){
lst.push(snapshot.val().E_mail);
//console.log(lst);
})
console.log(lst);
}
let lst = [];
login_btn.onclick = function() {login()};
I want to fetch all e-mails from the database, add them in the list and then loop through that list. Maybe this is not the best way, but that's what I'm working on. I could also just say if (snapshot.val().E_mail == e_mail){alert("there is such a user");}but the problem I have encountered and want to deal with is not that, it's the "callback" function inside login function. When I console the list in the outer function it shows an empty list as it does not run the inner function until it is done with the outer one. I understand this. But how can I avoid or fix this. I want to get the full list of e-mails to be able to loop through it then. Also, I don't know how to end the "loop" in Firebase, because it is sort of looping when it gets the e-mails. So I would like to stop at the moment when it finds a matching e-mail.
You're downloading all users to see if one name exists already. That is a waste of bandwidth.
Instead you should use a query to match the email you're looking for, and only read that node:
rootRef.orderByChild("E_mail").equalTo(e_mail).once("value", function(snapshot){
if (snapshot.exists()) {
// A node with the requested email already exists
}
})
In general, if you need to process all nodes, you'll want to use a value event, which executes for all matching nodes at once. So to get all users from the database, add them to a list, and then do something with that list:
rootRef.orderByChild("E_mail").once("value", function(snapshot){
var list = [];
snapshot.forEach(function(childSnapshot) {
list.push(childSnapshot.val());
});
console.log(list); // this will display the populated array
})
Note that you won't be able to access the list outside of the callback. Even if you declare the variable outside of the callback, it will only be properly populated inside the callback. See Xufox' comment for a link explaining why that is.

Attempting to use a global array inside of a JS file shared between 2 HTML files and failing

So I have one HTML page which consists of a bunch of form elements for the user to fill out. I push all the selections that the user makes into one global variable, allTheData[] inside my only Javascript file.
Then I have a 2nd HTML page which loads in after a user clicks a button. This HTML page is supposed to take some of the data inside the allTheData array and display it. I am calling the function to display allTheData by using:
window.onload = function () {
if (window.location.href.indexOf('Two') > -1) {
carousel();
}
}
function carousel() {
console.log("oh");
alert(allTheData.toString());
}
However, I am finding that nothing gets displayed in my 2nd HTML page and the allTheData array appears to be empty despite it getting it filled out previously in the 1st HTML page. I am pretty confident that I am correctly pushing data into the allTheData array because when I use alert(allTheData.toString()) while i'm still inside my 1st HTML page, all the data gets displayed.
I think there's something happening during my transition from the 1st to 2nd HTML page that causes the allTheData array to empty or something but I am not sure what it is. Please help a newbie out!
Web Storage: This sounds like a job for the window.sessionStorage object, which along with its cousin window.localStorage allows data-as-strings to be saved in the users browser for use across pages on the same domain.
However, keep in mind that they are both Cookie-like features and therefore their effectiveness depends on the user's Cookie preference for each domain.
A simple condition will determine if the web storage option is available, like so...
if (window.sessionStorage) {
// continue with app ...
} else {
// inform user about web storage
// and ask them to accept Cookies
// before reloading the page (or whatever)
}
Saving to and retrieving from web storage requires conversion to-and-from String data types, usually via JSON methods like so...
// save to...
var array = ['item0', 'item1', 2, 3, 'IV'];
sessionStorage.myApp = JSON.stringify(array);
// retrieve from...
var array = JSON.parse(sessionStorage.myApp);
There are more specific methods available than these. Further details and compatibility tables etc in Using the Web Storage API # MDN.
Hope that helps. :)

How to use $watch to see changes when updating a database record

I'm having nightmares on how to display on the UI what I have changed in my database. I have this scenario that I need to select certain titles and then I will click a button that will change its status.
Problem is when I select titles and then I click the change status button it don't automatically reflect on the UI. Here is my update function.
$scope.updateTitleStatus = function(statusId, cp){
ContentAssessmentService.updateSelectedTitles($scope.selectedTitles, statusId);
$scope.selAll = !$scope.selAll;
$scope.selectedTitles = [];
};
Here is my service.
this.updateSelectedTitles = function(selectedTitle, statusId){
var self = this;
_.forEach(selectedTitle, function(selectedTitle){
ContentAssessmentFactory.updateSelectedTitleStatus(selectedTitle.id, statusId);
});
};
Here is my array which is the selected title stored.
$scope.selectedTitles = [];
Can you tell me how to use $watch function? I don't know how to do it. I've done this but it doesn't work.
$scope.$watch(function($scope){
return $scope.selectedTitles;
}, function(newValue) {
$scope.selectedTitles = newValue;
console.log(newValue);
});
I just need to update the UI immediately without refreshing the page (that's my last option but trying not to) when I have click the change status button.
You are going to have to use polling or a websocket connection. $watch does not "watch" your database. It watches #scope variables that are usually bound to the view and reacts to changes there. It sounds like you are looking for something more like meteor.js that keeps an open websocket and will dynamically update the view when the database is changed from another client, background process etc. These are completely different things. To achieve this sort of behavior with angular, the easiest approach would be to poll your api incrementally and update models in angular when the api gives you modified data.

Create object and add to array of pointers - always replaces existing array

I have probably misunderstood the documentation somehow but cannot figure this out.
What I want to do, is to be able to create a new ClientContact and save it to an array of pointers called contacts in Clients table.
This is the relevant code:
var Client = Parse.Object.extend("Client");
var selectedClient = new Client();
// sets the objectId based on URL params
selectedClient.id = $routeSegment.$routeParams.id;
var ClientContact = Parse.Object.extend("ClientContact");
var contact = new ClientContact();
contact.set('name', 'test');
contact.set('desc', 'some description');
contact.set('phoneNumber', '123');
selectedClient.add('contacts', contact);
selectedClient.save().then(function() {
console.log('saved');
}, function(error) {
console.error(error);
});
As expected, the contact is automatically saved and added to contacts when the selectedClient is saved.
But if I run the same code again (in the testing this means refreshing the page), a new ClientContact is saved but it replaces the contacts array entirely.
That is, only the most recent ClientContact is associated to the Client, any new additions replaces the array, leaving only one pointer.
I hope there is an obvious an easy fix that I have simply failed to spot.
Ok seems I have located the problem.
I was assuming that array operations on an object was independant on the local representation.
What I did above was to construct an object based on a known objectId:
var Client = Parse.Object.extend("Client");
var selectedClient = new Client();
// sets the objectId based on URL params
selectedClient.id = $routeSegment.$routeParams.id;
Turns out that array operations like add and remove are performed based on the local information. So doing the above construction leaves my array, in the selectedClient object, empty at each page refresh. This was the cause of my array being replaced with a new single valued array.
In short, one should fetch an object before performing array operations it seems.
The reason for the construction above was to avoid having to re-query the Client object when navigating around an AngularJS based webpage. The solution was fortunately simple: loading the Client object once in a parent scope.
This moves outside the scope of the question. Just wanted to mention that as well.

Categories

Resources