Sending data to parse.com and update angular $scope - javascript

I am sending data to a Class at parse.com, I would like to run this function and update the $scope without having to reload the view.
To create a Programme running the function below works fine, however it sometimes does not update the view following creating a new programme and it requires a page refresh (when the whole function is called as seen at the bottom - getProgrammes();
getProgrammes = function() {
$ionicLoading.show();
var programmesArray = [];
var QueryProgramme = Parse.Object.extend("Programme");
var query = new Parse.Query(QueryProgramme);
query.equalTo("userId", userId);
query.find({
success: function(results) {
for(var i=0; i < results.length; i++) {
var object = results[i];
var programmeData = { title : object.get('programmeTitle'),
id : object.id,
exercises : object.get('exerciseData')
};
programmesArray.push(programmeData);
}
$scope.programmes = programmesArray;
$scope.$apply();
$ionicLoading.hide();
},
error: function(error) {
alert('You do not have any Programmes - please create one');
}
})
};
getProgrammes();
I think I may be hacking this by using $scope.apply() - therefore making it unreliable. Assistance on the correct function to use in order to automatically update $scope would be great.

I've been using a library found here:
https://github.com/brandid/parse-angular-patch
Essentially I just reference the parse-angular.js file, and then include the dependency in my app, e.g.:
angular.module('app', [
'parse-angular',
]);
Then I just use Parse queries anytime I like and they participate correctly with $scope and $apply. The library just does some simple wrapping on the Parse methods to make the async calls obey the rules of angular.

Related

Parse.com - secure sending data with javascript SDK

I'm building right now simple game with Angular JS and Parse.com cloud as my database.
My goal is in the and of the game, to store user score inside Parse cloud.
But how can i do this securly, when anyone can get access to my Parse keys, becouse they are visible in my js file, and simply recreate Parse Object with some fake data, and then store it in my database ?
ACL's it's not the point in this particular case - right now i just turn of write acl before save, to prevent users from changing they scores before save.
In my game i don't have any Parse Users - i want to all peaople play my game, without logging in.
What do you think about idea to make 'fake' user like in first answer in this post ( becouse Anonymous anonymous can't be create in JS parse SDK ), and then track the session and the user ?
Is it even helpful in my case ?
Maybe i should make some check in Cloude Code - like comparison Cookies or local storage data before saving in Parse ( it will make cheating in game harder but still possible ) ?
Below i present my whole service to show you what is all about:
angular.module('Parsedb', [])
.provider('Parsedbmanager', function() {
this.$get = function($q, $http) {
// new Parse constructor
var ParseHighScore = Parse.Object.extend('ParseHighScore');
// create new obj
var parseHighScore = new ParseHighScore();
this.parseInit = function() {
Parse.initialize('myKey', 'myKey');
};
this.setParsedb = function(newScore) {
// set val
parseHighScore.set('HighScore', newScore);
// save score to cloud
parseHighScore.save(null, {
success: function (parseHighScore) {
// protect from change saved obj
var acl = new Parse.ACL();
acl.setPublicReadAccess(true);
acl.setPublicWriteAccess(false);
parseHighScore.setACL(acl);
return parseHighScore.save();
},
error: function (parseHighScore, error) {
console.log('Failed to create new object, with error code: ' + error.message);
}
});
};
this.getParsedb = function() {
// need q to get this asynch
var deferred = $q.defer();
var query = new Parse.Query(ParseHighScore);
query.limit(5);
query.descending("HighScore");
query.find({
success: function(results) {
console.log("Successfully retrieved " + results.length + " scores.");
// resolve, if you have results
deferred.resolve(results);
},
error: function(error) {
deferred.reject(error.message);
}
});
return deferred.promise;
};
return this;
};
});
If you let the user to write to db then there will always be a situation where user can change data .. i think all you can do is, to abstract it from user

Watching Firebase query in angularjs

I'm building an application in Angular with Firebase and one aspect of it is one-to-one chat. I'm querying Firebase to see if a chat room exists already between the user currently accessing the application and the user they are attempting to chat with. If it exists, I am trying to apply that room to the scope as the selected room. I'm using "Messages" service to run the query.
this.roomQuery = function(user1ID, user2ID) {
roomsRef.orderByChild("user1").equalTo(user1ID).on("child_added", function(snapshot) {
if (snapshot.val().user2 == user2ID) {
self.selectedRoom = snapshot.key();
console.log(self.selectedRoom);
} else {
self.selectedRoom = null;
}
})
}
and in my controller I am using:
$scope.$watch(
function(){ return Messages.selectedRoom },
function(newValue, oldValue) {
$scope.selectedRoom = newValue;
}
)
This $scope.$watch method has worked for me with everything else and it seems to sometimes work in this case. The console log always prints out the correct value for Messages.selectedRoom, but the $scope.selectedRoom sometimes does not update. Any idea what is happening here? I'm very confused. If it's logging to the console properly, shouldn't it be updated in the scope?
Angular's $digest is unaware of when a your Firebase query completes. You might find it easier to use AngularFire in this case.
this.roomQuery = function(user1ID, user2ID) {
var query = roomsRef.orderByChild("user1").equalTo(user1ID);
return $firebaseObject(query).$loaded();
};
this.roomQuery("1", "2")
.then(function(data) {
// do your check here
});
The $firebaseObject() takes in a ref or a query and knows when to call digest on your behalf.
You might want to check out using resolve in the router to inject the roomQuery into the router, since it returns a promise with .$loaded().
David got me to the solution I needed. For anyone with a similar issue, here is how I implemented it:
this.roomQuery = function(user1, user2) {
var query = roomsRef.orderByChild("user1").equalTo(user1ID)
return $firebaseArray(query).$loaded();
}
I used $firebaseArray instead of Object and in my controller:
$scope.getRoom = function() {
Messages.roomQuery($scope.user1.id, $scope.user2.$id).then(function(data)
{
$scope.data = data;
for(var i=0, len = data.length; i < len; i++){
if (data[i].user2 == $scope.user2.$id) {
$scope.selectedRoom = data[i].$id;
}
}
}
)
}
Apologies for the variable names being a little confusing. I altered them for the sake of this post.

Select websql Data using Angular JS

I am trying to figure this out the best way to do this. I am trying to insert data into a WebSQL table and then select the data from the table and display on the screen using ng-repeat. I am using this Angular WebSQL Module https://github.com/paulocaldeira17/angular-websql#select-all.
So far, I can get the remote data and insert them into the local database. When I try to call the insert data, $scope.localproducts shows an empty array - console.log( $scope.localproducts) shows an empty array.
I use localproducts scope for my ng-repeat.
I can't get to return the ProductsFactory.localproducts array to my controller from the Factory's selectAllData function.
When clicks a button on my page, it calls the insertData function in my Controller.
What have I done wrong here? I am pretty new to angular so I would very much appreciate if someone can help me to improve the below code or suggest if there is a better way to do this.
.controller('DownloadProductsCtrl', ['$scope','ProductsFactory', function ($scope, ProductsFactory){
$scope.products = ProductsFactory.products;
$scope.localproducts = ProductsFactory.localproducts;
$scope.insertData = function(){
ProductsFactory.getRemoteData().then(function(results){
$scope.localproducts = ProductsFactory.localproducts;
console.log( $scope.localproducts); //This shows an empty array
});
}; }])
.factory('ProductsFactory', ['$webSql', function($webSql){
db = $webSql.openDatabase('myappdb', '1.0', 'Test DB', 2 * 1024 * 1024);
ProductsFactory = {};
ProductsFactory.products = [];
ProductsFactory.localproducts = [];
ProductsFactory.getRemoteData = function () {
return $http.get('./products/list.json')
.success(function (data) {
ProductsFactory.products = data;
ProductsFactory.insertData(data);
})
.error(function () {
console.error('Error');
});
};
ProductsFactory.insertData = function (data){
angular.forEach(data, function(value, key) {
db.insert('products', value).then(function(results) {
<!-- In here I like to count the total inserted items and display it on the page, but not sure sure how to send it to a scope in my controller -->
});
});
ProductsFactory.selectAllData();
};
ProductsFactory.selectAllData = function(){
db.selectAll("products").then(function(results) {
for(var i=0; i < results.rows.length; i++){
ProductsFactory.localproducts.push(results.rows.item(i)); //This added data to the array successfully.
}
console.log(ProductsFactory.localproducts); //This shows an empty array
});
};
return ProductsFactory;
}]);
Try with this resource as a start point.
https://gist.github.com/jgoux/10738978
https://github.com/paulocaldeira17/angular-websql/blob/master/angular-websql.js
The first one is very basic and easier to understand. The second more involved.

kendo grid template js with remote datasource

I got a table with remote datasource. in one cell I got the userID. Because I want to show the username instead of the user ID I made a custom template function:
function getUserName(pmcreator){
var user = '';
var data = ''
ds_userList.fetch(function(){
var data = this.data();
for(var i = 0, length = data.length; i < length; i++){
if(data[i].uID == pmcreator){
console.log(data[i].uLastname)
user = data[i].uLastname
}
}
});
return user
}
But its not working as it should, the cells stay empty. I got no errors but I see that the remote request to fetch the usernames is not completed before the grid is filled out. I thought the custom function of fetch is waiting for the results to return but it don't seems so.
Any Idea? I find thousends of examples but all with static local data. I need one with both remote, the grid conent and the template data.
This is probably due the fact that when yuo call the dataSource.fetch it fires off an async function, which causes the thread running the template to continue on. According to kendo you will need to return a control, then set the content of that control inside the callback.
Quick sample using Northwind categories...
Here is the template function
function getDetails(e) {
$.getJSON("http://services.odata.org/V3/Northwind/Northwind.svc/Categories", null, function(data) {
var category = data.value.filter(function(item, i) {
return item.CategoryID === e.CategoryID;
});
$("#async_" + e.CategoryID).html(category[0].Description);
});
return "<div id='async_" + e.CategoryID + "'></div>";
}
http://jsbin.com/ODENUBe/2/edit
I kept getting a recursive error maximum call stack when I just tried to fetch the dataSource, so I switched to a simple getJSON, but it should work pretty much the same.

Populate Ember.Select directly from Database

Let me explain my issue, I am trying to populate Ember.Select directly from database.
I have these routes:
this.resource('twod', function() {
this.resource('twoduser', {
path : ':user_id'
});
});
In twoduser, I am displaying a full information about a single user. In that view, I have a Select Box as well, which end user will select and then with a button, he can add the user to a team that he selected from Ember.Select.
I tried to do this,
App.TwoduserController = Ember.ArrayController.extend({
selectedTeam : null,
team : function (){
var teams = [];
$.ajax({
type : "GET",
url : "http://pioneerdev.us/users/getTeamNames",
data : data,
success : function (data){
for (var i = 0; i < data.length; i ++){
var teamNames = data[i];
teams.push(teamNames);
}
}
});
return teams;
}.property()
})
Then in my index.html:
{{view Ember.Select
contentBinding="team"
optionValuePath="teams.team_name"
optionLabelPath="teams.team_name"
selectionBinding="selectedTeam"
prompt="Please Select a Team"}}
But when I do this, for some reason it interferes with Twoduser and I am not able to view the single user.
Furthermore, here's a sample JSON response I will get through the url:
{"teams":[{"team_name":"Toronto Maple Leafs"},{"team_name":"Vancouver Canuck"}]}
Moreover, I am fetching all users using Ajax like this:
App.Twod.reopenClass({
findAll : function() {
return new Ember.RSVP.Promise(function(resolve, reject) {
$.getJSON("http://pioneerdev.us/users/index", function(data) {
var result = data.users.map(function(row) {
return App.Twod.create(row);
});
resolve(result);
}).fail(reject);
});
},
findBy : function(user_id) {
return new Ember.RSVP.Promise(function(resolve, reject) {
var user = App.Twod.create();
$.getJSON("http://pioneerdev.us/users/byId/" + user_id, function(data) {
var result = user.setProperties(data.user);
resolve(result);
}).fail(reject);
});
}
});
Though there's one thing, I have a separate Teams route:
this.resource('teamview', function(){
this.resource('teamviewdetail', {
path : ':team_id'
});
});
Which shows all the teams and a single team when you click on a single team.
Can I use that TeamviewController? or Can I fetch team names from Twoduser Controller and push names to the array as I mentioned before?
More Information:
If I use the way I mentioned, I get this error:
Uncaught TypeError: Object [object Object] has no method 'addArrayObserver'
Here's a working jsfiddle on the issue I am experiencing. You can select "Storyboard" from the Designation & then select the user. That will reproduce the issue.
One more Update: Seems using ObjectController instead of ArrayController issue solves the addArrayObserver issue. But still I can't get the teams in the Ember.Select.
The biggest issue here is that you use Array#push instead of pushObject. Ember needs the special methods in order to be aware of changes. Otherwise, it will continue to think that the array of teams is as empty as when you first returned it. Second biggest issue is that your ajax success call isn't accessing the returned data properly.
Also, optionValuePath and optionLabelPath are relative to the individual select option view, so they should start with content, which is the individual item as set on the view. So: content.team_name

Categories