Angularjs Passing array between controllers - angularjs

I have been through several tutorials and posts about this topic and still can't seem to figure out what is wrong with my code. To me it seems I am having scoping issues with the data within my service. My code is split up into separate files. Here is my code:
github link : https://github.com/StudentJoeyJMStudios/PetPinterest.git
//in dataService.js
var app = angular.module('se165PetPinterestWebApp');
app.service('SharedData', function ()
{
var categoryOfSelectedAnimals = [];
this.setCatOfSelAnimals = function(pulledCategoriesFromParse)
{
categoryOfSelectedAnimals = pulledCategoriesFromParse;
console.log('after assignment in set::' + categoryOfSelectedAnimals);
};
this.getCatOfSelAnimals = function()
{
console.log('in get::::' + categoryOfSelectedAnimals);
return categoryOfSelectedAnimals;
};
});
in my first controller to set the data in signup.js
app.controller('SignupCtrl',['$scope', 'SharedData', function ($scope, SharedData)
{
var Categories = Parse.Object.extend('Categories');
var query = new Parse.Query(Categories);
query.find({
success: function(results)
{
$scope.availableCategoriesOfAnimals = results;
SharedData.setCatOfSelAnimals(results);
},
error: function(error)
{
alert('Error: ' + error.code + ' ' + error.message);
}
});
};
}]);
Then in my other controller trying to get the data from the array within my service:
var app = angular.module('se165PetPinterestWebApp');
app.controller('CatSelCtrl', function ($scope, SharedData)
{
$scope.availableCategoriesOfAnimals = SharedData.getCatOfSelAnimals();
});
When I print the contents from the SharedData.getCatOfSelAnimals I get 0 every time. Please help. Thank you very much in advance.
EDIT: After playing around with a string a bit I am finding the changed string in the set function is not saved into the service and when I call my get function within my service the string is not changed from the set method. Please help, thank you in advance.
EDIT: So it looks like when I navigate to new page by using window.location.href = '../views/categorySelection.html'; in my signup.js it reloads my dataService.js which re-sets my variables back to nothing. Does anyone have any ideas as to how to fix this?

Edit
First: why you lose data
You need to setup routing properly. Right now you are not changing views but rather using window.location.href to load a new bootstrap file (dashboard.html), i.e. everything saved in memory will be lost. So you have been doing it right, sort of, but the moment you change to dashboard.html all data from Parse is lost.
You can solve this by configuring routes and use $location.url() to change URL. Read more about angular.route here: https://docs.angularjs.org/api/ngRoute/service/$route
The angular way
After looking at your code and running your app I think we need to take a step back. Angular is tricky to get used to but there is a lot of good tutorials. I think you might wanna read some of them to get a better grasp of how it works and how to setup and build your app.
Start here: http://www.airpair.com/angularjs
Boilerplate
Found this boilerplate for an Angular app using Parse. It might be something you could use. https://github.com/brandid/parse-angular-demo
Original
Or an even quicker way to empty $scope.availableCategoriesOfAnimals and then merge new data without breaking reference:
$scope.availableCategoriesOfAnimals.length = 0;
Array.prototype.push.apply($scope.availableCategoriesOfAnimals, pulledCategoriesFromParse);

You are breaking the reference on assignment. This is a JavaScript issue, not an angular one for that matter ;)
Try this in your set function:
categoryOfSelectedAnimals.length=0;
pulledCategoriesFromParse.forEach(function (e) {categoryOfSelectedAnimals.push(e)});
in stead of reassigning
edit: angular extend works on objects, not arrays, so replaced it with a bit of JS.

Related

Angular translate - When multiple loader it execute only the last one

I've got a project using angular translate with a custom loader.
Basically, this is the config in my provider (which is working perfectly).
Provider (stuff executed in the config of my app)
$translateProvider.useSanitizeValueStrategy('sanitize');
$translateProvider.useLoader('componentsTranslationLoader');
$translateProvider.preferredLanguage($language);
As you can see, I use my own componentsTranslationLoader. It does the stuff as expected.
Factory (componentsTranslationLoader)
return function(options) {
var deferred = $q.defer();
var translations = {};
$http.get('languages/components/' + options.key + '.json').success(function(keys) {
translations = keys;
deferred.resolve(translations);
});
return deferred.promise;
};
Everythings is fine from here.
I have to use a library in this project (company's one, I can edit it), and this library also has his own angular translate stuff (basically the same thing).
It has a custom loader, initialized into the config.
When my project is executed, I expect that both loader do their stuff and extend the language with their keys.
It didn't.
Only the last loader is executed (see it with logs).
So, how can I resolve this conflict properly please ?
Is there something wrong with my way of using angular translate ?
Thanks for the help guys.
Edit (more informations added)
I added more call like this one into the config with different 'fake' loader:
$translateProvider.useLoader('aFakeLoaderWithLogs');
And the problem still the same, only the last one into the config is called.
I searched for topics with similar issues and found nothing, even in the documentation.
Try this approach of merging responses. Works for me very well.
function customLoader($http, $q, localeUrl, errorCodeUrl) {
return function (options) {
var deferred = $q.defer();
var translations = [];
$q.all([
$http.get(localeUrl + "locale-" + options.key +".json"),
$http.get(errorCodeUrl + "?lang=cs")
]).then(function(response, status) {
translations.push(response[0].data);
translations.push(response[1].data);
console.log(translations);
deferred.resolve(translations);
return translations;
});
return deferred.promise;
};
}

Is it possible to resolve AngularJS promises in a template?

in all documentation and tutorials for HTTP request i found that recomanded usage is something like:
var ax = {
getCaseData: function() {
api.cases.getCase(caseManager.data.id).then(function(res){
// puting my response to $scope.something
$scope.something = res.data;
});
},
}
I really don't feel like senior so please tell me if I am wrong but I thing many times you don't need to store something like this on scope, for example you want to just resolve promise once and display data (you are not doing anything else with it)
So I was thinking if is there an option to make a promise as:
var ax = {
getCaseData: function() {
return api.cases.getCase(caseManager.data.id);
},
}
and after this call tempalte something like:
<li ng-repeat="ax.getCaseData()"></li>
This was handled automatically in old version of AngularJS (<1.2), but was removed since then.
Some posts state that the feature can be re-enabled manually by adding this line in your ".config" function :
$parseProvider.unwrapPromises(true);
But this is not advised as a solution. You are currently doing it the right way.
If you have plenty of cases like this, you can probably create your own "promises wrapper" function, and use it from your template.
See : https://stackoverflow.com/a/19472065/1636977

Angular-fullstack get user id

I'm using angular-fullstack to build a single page application, and in one of my controllers I'm trying to assign a user's id to a variable. The code
$scope.getCurrentUser = Auth.getCurrentUser;
returns
function () {
return currentUser;
}
This works fine for displaying in my view as my angular code can interpret the function and display the user id using {{getCurrentUser()._id}} which I'm assuming evaluates the promise and displays the code to the view.
My question is how do I assign $scope.getCurrentUser = Auth.getCurrentUser; to a variable in my controller? Whenever I do so, I get undefined variables. I've tried:
$scope.getId = Auth.getCurrentUser()._id;
console.log($scope.getId); //undefined
$scope.getId = Auth.getCurrentUser();
console.log($scope.getId._id); //undefined
I've read forum posts like this and this that explain that these methods are meant to be returned the way they are. Another post that is basically the same question as mine, but I'm still confused how to store the user id becuase the answer was hinting it was console.log that was the issue. Any help would be greatly appreciated, thanks.
Try the following and let me know how this works out:
angular.module('yourModuleName').controller('YourController', ['$scope', 'Authentication',
function($scope, Authentication) {
var authentication = Authentication;
$scope.getId = authentication.user._id;
console.log($scope.getId);
}
]);
Make sure Authentication is included in your controller.

retrieve data from firebase (angularjs)

UPDATE : find my answer here
A little clarity on getting key values using AngularFire v2?
I looked for many sources before asking a simple question but Im just sarting with firebase and I can't manage to use the data the way I want. What I need, is to retrieve two int in my controller (how much "yes" and how much "no" linked to a question.
the data model is the following
question/id/(text, yes, no)
I have a service where I call my data using an id
app.service('QuestionService', function($firebase,$q) {
var _this = this;
//initialize Firebase
var ref = new Firebase('https://basename.firebaseio.com/question');
this.get = function(nb){
var QuestionObject = ref.child(nb);
return $firebase(QuestionObject);
};
return this;
});
I have a controller function where I call some data using a random id
$scope.pickQuestion = function(){
var randomnumber = Math.ceil(Math.random() * 3);
$scope.message = QuestionService.get(randomnumber);
};
and then it works great so I can have something like
{{message.yes}} or {{message.no}} and get the corresponding integer.
My issue, what I want to do, is to pass this "message.no" value to my controller. I don't know what to do. I can't manage to get the value directly inside the controller (it works only inside the view) and I can't manage to pass the value to my controller from the view. I tried a
ng-init="functionName({{message.yes}}, {{message.no}})"
but it return an error into the console. (however the source a displayed correctly)
Does someone could guide me into the right direction?
Thanks

I can't seem to find a way to fetch a specific record from Firebase

This is a simple service I've built for Firebase for an application. I've had to jury-rig some elements and I've made absolutely sure I am using the latest versions of firebase and angular fire since it seems to be changing pretty fast. These first few lines are pretty straightforward,
app.factory('Ship', function ($routeParams, $firebase, FIREBASE_URL) {
var ref = new Firebase(FIREBASE_URL + 'ships');
The problems begin here. Depending on what I intend to do with the firebase object, at times it needs to be $asObject, at other times not. It depends on the tutorial and the most recent ones would seem to indicate that
var shipsObj = $firebase(ref).$asObject(); // Is this necessary
var ships = $firebase(ref); // in the most modern version?
var Ship = {
all: shipsObj, // This works fine
create: function (ship) {
return shipsObj.$add(ship); // This also works fine
},
find: function (shipId) {
console.log($routeParams.shipId); // <--this ID appears as the correct numerical ID
Then, there is the next six lines, NONE of which work. They all produce an error indicating that they are undefined.
console.log(shipsObj.$child(shipId));
console.log(ships.$child(shipId));
console.log(shipsObj.$getRecord(shipId));
console.log(ships.$getRecord(shipId));
console.log(ships.$keyAt(shipId));
console.log(shipsObj.$keyAt(shipId));
},
I won't bore you with repeating the next method multiple times as well, but $remove isn't working either.
delete: function (shipId) {
return ships.$remove(shipId);
}
};
return Ship;
});
Assuming your using v0.8 of AngularFire you'll want to use $asObject() or $asArray() to get at the actual data. Here's the official blog post that discusses the changes in v0.8: https://www.firebase.com/blog/2014-07-30-introducing-angularfire-08.html
So to access a ship by its id you could do:
var shipsObj = $firebase(ref).$asObject();
console.log(shipsObj[shipId]);
You may also want to take a look at the API docs for AngularFire: https://www.firebase.com/docs/web/bindings/angular/api.html
A lot changed in v0.8 and it just came out (July 2014) so if you're basing your code on anything older than that then it probably won't work

Resources