Angular factory not loading data - javascript

I'm trying to move http calls to angular factory but not sure why data not loaded. The issue is related to the customersController, for now I load data locally but eventually will move it to $http
app.factory('apiFactory', ["apiFactory", "$http", (apiFactory, $http) ->
factory = {}
customers = [
{ name: 'Apple', city: 'Cupertino' },
{ name: 'Google', city: 'SF' }
]
factory.getCustomers ->
customers
])
Here is Plunker http://plnkr.co/edit/itYnyzg2uS5xc6MJIIkE?p=preview

Because you were facing a circular reference.
You don't need apiFActory while defining apiFactory, hence circular reference.
Factory/Service should produce an API to be used by controller
Pardon my coffee script, if I am wrong anywhere. I tried to co-relate it to JavaScript for the API method. I may be wrong with the sytnax.
app.factory('apiFactory', ["$http", ($http) ->
factory = {}
customers = [
{ name: 'Apple', city: 'Cupertino' },
{ name: 'Google', city: 'SF' },
{ name: 'Mont Blanc', city: 'Paris' }
]
return {
getCustomers: () ->
customers
}
])
Refer this modified version of PLUNKR

Related

Angular - define modules in multiple files

I have the following in app.js
config = angular.module('config', [])
.constant('Constants', {
Car: 'BMW',
Phone: 'G4'
});
services = angular.module('services', ['config']);
controllers = angular.module('controllers', ['config', 'services']);
app = angular.module('myApp', ['config', 'controllers']);
I want to move the "config" module definition to a separate file as I'm expecting it to grow bigger.
Is it possible to move the below portion to a separate file:
config = angular.module('config', [])
.constant('Constants', {
Car: 'BMW',
Phone: 'G4'
});
There is no problem with doing that.
You just need to make sure the config module will be loaded before the app module
You've chosen very bad structure for your angular app. Please check this url https://scotch.io/tutorials/angularjs-best-practices-directory-structure
And about your question. Instead of using caching variables just do next thing:
file0: angular.module('config',[]);
file1: angular.module('config').constant('Constants', {Car: 'BMW', Phone: 'G4'});
file2: angular.module('config').constant('Constants2', {Car: 'BMW', Phone: 'G4'});

Ionic- Angular Js - Store array locally

Hello I am developing an Ionic app and I have an array that I want to push items on to it, but not lose the data when I change screens. Also, I do not want to use a database. Is there any other way? to add to an existing array and store that array locally?
$scope.tasksCollection = [
{ info: 'Go studying', measured: 'no', total: 1, done: 1, id: 1 },
{ info: 'Go to the beach', measured: 'no', total: 1, done: 1, id: 2},
{ info: 'Run', measured: 'yes', total: 30, done: 15, id: 3}
];
$scope.tasksCollection.push({
info: $scope.taskInfo,
measured: $scope.result,
total: total,
done: 0,
id: $scope.tasksCollection.length
})
The add function is working perfectly I just loose the data when changing states.
If you want to keep data between controllers either use a service or local storage if you want to keep the data even when you quit the app.
Service example
Further angular documentation regarding services: https://docs.angularjs.org/guide/services
service.js:
angular.module('yourmodule.services')
.service('Tasks', [function () {
var collection = {
tasks: []
};
return {
getTasks : function(){ return collection.tasks; }
}
}]
);
controller.js
angular.module('yourmodule.controllers')
.controller('TaskCtrl', ['$scope', 'Tasks',
function($scope, Tasks){
$scope.Tasks = Tasks //Expose service to template
$scope.addTask = function(){
Tasks.getTasks().push({name : 'a new task'});
}
}]);
Local storage example
This is an excellent library which provides easy localstorage access for angularjs: https://github.com/grevory/angular-local-storage
angular.module('yourmodule.controllers')
.controller('TaskCtrl', ['$scope', 'localStorageService',
function($scope, localStorageService){
$scope.collection = {
tasks : localStorageService.get('tasks') || [];
}
$scope.addTask = function(){
$scope.collection.tasks.push({name : 'a new task'});
localStorageService.set('tasks', $scope.collection.tasks);
}
}]);
How about HTML5's locaStorage?
See Ionic formulas on Using Local Storage.

Angular JS and Store DB like persistance

I've got an AngularJS app with a movies array in my controllers.
app.controller("MoviesListCtrl", ["$scope",
function($scope) {
$scope.movies = [
{
id:1,
originalTitle:'Gone with the Wind',
year: 2008
},
{
id:2,
originalTitle:'Back To The Future',
year: 1988
}
];
$scope.addMovie = function(){
$scope.movies.push({
id:3,
originalTitle: 'Mitchell and Jackie'
})
};
}
]);
I'd like to simply store these objects on a database, and be able to find them by their properties. I'm using node-webkit, and about data storage, the developer gives the example of StoreDB (https://github.com/rogerwang/node-webkit/wiki/Save-persistent-data-in-app - https://github.com/djyde/StoreDB/blob/master/README_EN.md).
I find StoreDB really simple, and it seems to fit my needs. But how can I bind it with Angular ? Have you got an equivalent made for Angular ?
Thank you

$http dependency injection throwing error

I've been working on the CodeSchool AngularJS app, which I've understand so far, but when I began using dependency injections, specifically, $http in order to make an call for my JSON data the app stops working, and I don't know why. Originally with the first line uncommented the app worked as it should using the variable gems declared within the closure, which is exactly the same code now found in products.json. I commented out the first line of the controller, and added the appropriate changes to for dependency injection, but now the app doesn't load at all, and it throws the error found below (also see $http-injection.png).
app.controller('StoreController', [ '$http', function($http) {
//this.products = gems; <-- works like this with data in closure
var store = this;
store.products = [ ]; // no erros on page load
$http.get('/data/products.json').success(function( data ) {
store.products = data;
});
}]);
Error: [ngRepeat:dupes] http://errors.angularjs.org/1.3.0-beta.10/ngRepeat/dupes?p0=product%20in%20storeCtrl.products&p1=string%3A%0D
at Error (native)
at http://angularjs.dev/angular-1.3/angular.min.js:6:457
at http://angularjs.dev/angular-1.3/angular.min.js:204:24
at Object.<anonymous> (http://angularjs.dev/angular-1.3/angular.min.js:108:144)
at Object.applyFunction [as fn] (<anonymous>:778:50)
at g.$digest (http://angularjs.dev/angular-1.3/angular.min.js:109:211)
at g.$delegate.__proto__.$digest (<anonymous>:844:31)
at g.$apply (http://angularjs.dev/angular-1.3/angular.min.js:112:325)
at g.$delegate.__proto__.$apply (<anonymous>:855:30)
at g (http://angularjs.dev/angular-1.3/angular.min.js:73:287) angular.js:10811
(anonymous function) angular.js:10811
(anonymous function) angular.js:7962
g.$digest angular.js:12560
$delegate.__proto__.$digest VM8634:844
g.$apply angular.js:12858
$delegate.__proto__.$apply VM8634:855
g angular.js:7380
x angular.js:8527
y.onreadystatechange
product.json
[
{
name: 'Hexagonal',
price: 250.00,
description: 'The six faces of the hexaonal gem have a habit to excite the eye, and attract good luck.',
canPurchase: true,
soldOut: false,
images: [ ],
reviews: [
{
stars: 5,
body: "I love this product!",
author: "mtpultz#gmail.com"
},
{
stars: 1,
body: "This product sucks!",
author: "mtpultz#hater.com"
}
]
},
{
name: 'Dodecahedron',
price: 1015.25,
description: 'Some gems have hidden qualities beyond their luster, beyond their shine... Dodeca is one of those gems.',
canPurchase: true,
soldOut: false,
images: [
"img/gem-06.gif",
"img/gem-02.gif",
"img/gem-01.gif"
],
reviews: [
{
stars: 3,
body: "I think this gem was just OK, could honestly use more shine, IMO.",
author: "mtpultz#hotmail.com"
},
{
stars: 4,
body: "Any gem with 12 faces is for me!",
author: "mtpultz#casensitive.ca"
}
]
},
{
name: 'Pentagonal Gem',
price: 5.95,
description: 'Origin of the Pentagonal Gem is unknown, hence its low value. It has a very high shine and 12 sides however.',
canPurchase: true,
soldOut: false,
images: [
"img/gem-02.gif",
"img/gem-06.gif",
"img/gem-01.gif"
],
reviews: [
{
stars: 4,
body: "The mystery of the Pentagonal Gem makes it sooo fascinating!",
author: "mtpultz#peanutbutter.com"
},
{
stars: 5,
body: "I can't get enough of the five faces of the Pentagonal Gem!",
author: "mtpultz#ketchup.ca"
}
]
}
];
Originally I was going to try and figure out how to use $log as well, and when I had $log injected it appears as if the json is received (see $http-and-$log-injection.png attached) based on the chrome batarang plugin's output, but the app still doesn't work either way, only the JSON appears on right side of batarang output.
app.controller('StoreController', [ '$http', '$log', function($http, $log) {
//this.products = gems;
var store = this;
store.products = [ ]; // no erros on page load
$http.get('/data/products.json').success(function( data ) {
store.products = data;
});
}]);
You shouldn't use the minified version of Angular while developing. You'll get better error messages when using the non-minified version. But even when you're using the minified version you can get a pretty good idea of what the problem is by visiting the url mentioned first in the exception: http://errors.angularjs.org/1.3.0-beta.10/ngRepeat/dupes?p0=product%20in%20storeCtrl.products&p1=string%3A%0D
It seems like you have duplicates in products.json. Without seeing the whole contents of products.json or any of your markup that would be my best guess.
--
Update: It seems like data is a string and not an array. This is probably because the response body from the server is not properly formatted JSON. Instead of traversing objects in an array, ng-repeat traverses characters in a string and throws an error on the second tab character (encoded as %0D) it detects. I've created a plnkr with properly and a bad response as an example: http://plnkr.co/edit/XbPuXkykzv36NyH3sSeu?p=preview
You should use $scope:
$scope.store = {};
$scope.store.products = [ ]; // no erros on page load
$http.get('/data/products.json').success(function( data ) {
$scope.store.products = data;
});
ngRepeat:dupes error occurs if there are duplicate keys(values in your array/json) in an ng-repeat expression, this is because AngularJS uses keys to associate DOM node with ng-repeated items. The requested data products.json may have fields that contain the same value, to solve this, you can append a track by $index expression in your ng-repeat so that the association of DOM node items will be keyed by the index of the your array/json instead of the value of each item.
E.G.
<div ng-repeat="product in Store.products track by $index"></div>

Make ember to resolve hasMany relationship when loading

I'm currently facing a big problems for days. I'm using ember simple-auth plugin which provide me a session object accessible through the code or the templates. That session object store the account information such as username, id and rights.
My models are like this :
App.Right = DS.Model.extend({
label: DS.attr('string', { defaultValue: undefined })
});
App.Right.FIXTURES = [
{
id: 1,
label: 'Admin'
}, {
id: 2,
label: 'Manager'
}, {
id: 3,
label: 'User'
}
];
App.User = DS.Model.extend({
username: DS.attr('string'),
rights: DS.hasMany('right', {async: true})
});
App.User.FIXTURES = [
{
id: 1,
username: "Someone",
rights: [1]
}
];
Then I have (as specified on the simple-auth documentation) this setup :
App.initializer({
name: 'authentication',
initialize: function(container, application) {
Ember.SimpleAuth.Session.reopen({
account: function() {
var userId = this.get('userId');
if (!Ember.isEmpty(userId)) {
return container.lookup('store:main').find('user', userId);
}
}.property('userId')
});
...
}
});
Inside one of my view I'm doing this:
this.get('context.session.account.rights').toArray()
but it gives me an empty array. That piece of code is executed inside an Ember.computed property.
The question is how can I resolve the childrens of account before rendering the view ?
Since async: true this.get('context.session.account.rights') will return a promise object so you will have to use this.get('context.session.account.rights').then(... see: http://emberjs.com/api/classes/Ember.RSVP.Promise.html#method_then
Okay so I finally got it to work. It doesn't solve the original question because the original question was completely stupid. It's just IMPOSSIBLE to resolve relationships synchronously when you use the async: true. Trying to resolve it in advance is NOT the solution because you will still not know when it has actually resolved.
So here is the solution:
$.each(this.get('cellContent.buttonList'), function(i, button) {
button.set('hasAccess', false);
this.get('context.session.account').then(function(res) {
res.get('rights').then(function(result) {
button.set('hasAccess', Utils.hasAccess(result.toArray(), button.rights));
});
});
});
Using the following cellContent.buttonList definition:
buttonList: [
Ember.Object.create({
route: 'order',
label: 'Consult',
rights: 'all'
}), Ember.Object.create({
route: 'order.edit',
label: 'Edit',
rights: [1, 2]
})
]
Explanation
We have to use Ember.Object in order to have access to the set method. Using an Ember object is very handy. It allows us to change the value of properties after the render process making the view to update according to the new value you just set.
Because it updates the view, you don't have to care anymore whether your model has resolved or not.
I hope this will help people as much as it helps me.

Categories

Resources