I have two controllers Order and Meal. This code made an error when I choose 2 the same meals:
$scope.meal is undefined
What can I do wrong?
angular.module('mocs')
.controller('ordersCtrl', [
'$scope',
'orders',
'meals',
'myService',
function($scope, orders, meals, myService){
$scope.orders = orders.orders;
$scope.meal = myService.getOrder();
if (!angular.isUndefined($scope.meal)) {
orders.create({
meal_id: parseInt($scope.meal.id),
status: "ordered",
});
}
...
Even if error exist my wrong meal is saving to orders.
myService code:
.factory('myService', function() {
var mealToOrder = {};
return {
setOrder: function(meal) {
return mealToOrder.meal = meal;
},
getOrder: function() {
return mealToOrder.meal;
}
};
});
my Factory:
angular.module('mocs')
.factory('orders', [ '$http',function($http){
...
o.create = function(order) {
return $http.post('/orders.json', order)
.success(function(data){
o.orders.push(data);
order = '';
});
};
return o;
}]);
Related
I am having issues returning the data to html. Here is my code.
HTML:
<input type="text" ng-model="userEntry" typeahead-template- url="searchResults.html" uib-typeahead="data.EMPLOYEE_NAME for data in search($viewValue)" uib-typeahead-wait-ms="500" />
<script type="text/ng-template" id="searchResults.html">
<div>
<div>
{{match.model.EMPLOYEE_NAME}}
</div>
</div>
</script>
Factory:
App.factory('SearchService', ['$http', '$q', function($http, $q) {
var url = '/api/GetUsers';
var deffered = $q.defer();
var data = [];
var myService = {};
myService.async = function() {
$http.get(url)
.success(function(d) {
data = d;
//console.log(d);
deffered.resolve();
});
return deffered.promise;
};
myService.data = function() {
return data;
};
return myService;
}]);
Controller:
App.controller('SearchUser', ['$scope', 'SearchService', function($scope, SearchService) {
$scope.search = function(val) {
SearchService.async().then(function() {
$scope.data = SearchService.data();
console.log($scope.data);
});
};
}]);
Here is the data coming back:
[{
"EMPLOYEE_ID": "246",
"NETWORK_ID": "onky",
"EMPLOYEE_NAME": "Aaron",
"DIRECTOR_NAME": "Blood",
"VP_NAME": "Sigi"
}, {
"EMPLOYEE_ID": "802",
"NETWORK_ID": "c0",
"EMPLOYEE_NAME": "Georges",
"DIRECTOR_NAME": "Johnson",
"VP_NAME": "Sigi"
}, {
"EMPLOYEE_ID": "124",
"NETWORK_ID": "abr",
"EMPLOYEE_NAME": "MaryamJ.",
"DIRECTOR_NAME": "James",
"VP_NAME": "Sigi"
}]
The use of success is deprecated, you want to change that to use then. You're also returning the promise outside of your success function, so you're returning it too early. It should look more like this:
myService.async = function () {
return $http.get(url)
.then(function (d) {
data = d;
//console.log(d);
deffered.resolve();
return deffered.promise;
});
};
I am having fits trying to get my factory/service function to work from my controller. I have seen many threads on this, and have tried various solutions, to no avail, so it leads me to believe I'm missing something simple. Here's the code (error message provided below):
'use strict';
var smacApp = angular.module('smacApp', ['ngRoute']);
smacApp.config(function($routeProvider) {
$routeProvider
.when("/login", {
templateUrl: "templates/login.html",
controller: "LoginController"
})
});
smacApp.factory('AuthenticationService', function() {
var users = ["Bob", "Joe"];
return {
all: function() {
return users;
},
first: function() {
return users[0];
}
};
});
smacApp.controller('LoginController', function($scope, AuthenticationService) {
$scope.users = AuthenticationService.all();
console.log($scope.users);
});
smacApp.run.$inject = ['$rootScope', '$routeParams'];
smacApp.run(function($rootScope, $routeParams) {
});
The error message I am receiving is:
angular.js:9778TypeError: AuthenticationService.all is not a function
at new <anonymous> (http://localhost/smac3/app.js:61:39)
at d (http://localhost/smac3/lib/angular/js/angular.min.js:34:265)
at Object.instantiate (http://localhost/smac3/lib/angular/js/angular.min.js:34:394)
at http://localhost/smac3/lib/angular/js/angular.min.js:66:112
at link (http://localhost/smac3/lib/angular/js/angular- route.js:913:26)
at J (http://localhost/smac3/lib/angular/js/angular.min.js:53:345)
at f (http://localhost/smac3/lib/angular/js/angular.min.js:46:399)
at http://localhost/smac3/lib/angular/js/angular.min.js:46:67
at http://localhost/smac3/lib/angular/js/angular.min.js:47:303
at u (http://localhost/smac3/lib/angular/js/angular.min.js:51:28) <div ng-view="" id="container" class="ng-scope">
Any help is greatly appreciated!
Maybe the syntax for your factory is correct, but I've always written them more like this:
smacApp.factory('AuthenticationService', function() {
var factory = this
factory.users = ["Bob", "Joe"];
factory.all = function() {
return factory.users;
};
factory.first = function() {
return factory.users[0]
}
return factory;
}
or
smacApp.factory('AuthenticationService', function() {
var factory = this
factory = {
users: ["Bob", "Joe"],
all: function() { return factory.users },
first: function() { return factory.users[0] }
}
return factory;
}
I have a template in which I output the values (movie titles) from my database,
%div{"ng-repeat" => "movie in movies"}
{{ movie.title }}
And a template in which users can input a movie title,
%div{"ng-controller" => "searchCtrl", :id => "container_search"}
#addMovie{"ng-controller" => "addMovieCtrl"}
%div{"ng-click" => "addMovie()"}
%input{:type => "text", "ng-model" => "title"}
addMovie action.
When a user types in a movie title in the inputfield and clicks the div it gets saved into the database, and when I refresh the page I can see the result. But I want this to happen asynchronously (at the same time, right?).
This is the controller,
angular.module('addMovieseat')
.controller('movieOverviewCtrl', [
'$scope', 'movieService', function($scope, movieService) {
movieService.success(function(data) {
$scope.movies = data;
});
}
]);
And this is the service,
angular.module('addMovieseat')
.factory('movieService', ['$http', function($http) {
return $http.get('movies.json')
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
}])
.factory('movies', ['$http', function($http){
var o = {
movies: []
};
o.create = function(movie){
return $http.post('/movies.json', movie).success(function(data){
o.movies.push(data);
});
};
return o;
}])
Your service should not do an HTTP request as soon as it's instanciated, and then always return the same result. Instead, it should provide a method that allows getting the movies.
Once that is done, you can simply call the service again right after saving a new movie:
angular.module('addMovieseat')
.factory('movieService', ['$http', function($http) {
return {
loadMovies: function() {
return $http.get('movies.json');
}
};
}])
.factory('movies', ['$http', function($http){
return {
create: function(movie) {
return $http.post('/movies.json', movie);
}
};
}]);
and your controller can now simply do
angular.module('addMovieseat')
.controller('movieOverviewCtrl', [
'$scope', 'movieService', 'movies', function($scope, movieService, movies) {
var init = function() {
movieService.loadMovies().then(function(response) {
$scope.movies = response.data;
});
};
init();
$scope.save = function() {
movies.create({title: $scope.title}).then(init);
};
}]);
Note that you're making your own life more complex than it should by defining two services instead of just one that would have a loadMovies() and a create() functions.
My basic question is what is the best practice for keeping the model and the view in synch in angular, especially when it is a single object. I have been trying to play around with promises, but cant seem to get anything to work. The thing I am trying to do is increment the upvotes on post, a popular example.
ok heres the code: function I am working on is the incrementUpvotes function.
Factory:
(function() {
ngNewsApp.factory('posts', posts);
posts.$inject = ['$http', '$q'];
function posts($http, $q) {
var service = {
postList: [],
getPosts: function() {
return $http.get('/posts').success(function(data) {
angular.copy(data, service.postList);
});
},
savePost: function(post) {
return $http.post('/posts', post).success(function(data) {
service.postList.push(data);
});
},
getPost: function(id) {
return $http.post('/posts/' + id).success(function(result) {
return result.data;
});
},
upvote: function(post) {
return $http.put('/posts/' + post._id + '/upvote');
}
};
return service;
}
})();
Controller:
ngNewsApp
.controller('MainCtrl', ['$scope', 'posts', function ($scope, posts) {
$scope.posts = posts.postList;
$scope.addPost = function() {
if(!$scope.title || $scope.title === '') {
return;
}
posts.savePost({
title: $scope.title,
link: $scope.link
});
$scope.title = '';
$scope.link = '';
};
$scope.incrementUpvotes = function(post) {
posts.upvote(post).success(function(post) {
post.upvotes++;
});
};
}]);
I am pretty certain I'm following all the rules:
$get() is defined.
injecting properly into the controller
configuring in the initial app def before it's instantiated
Here is a fiddle
angular.module('app', function($httpProvider, $locationProvider, MockServiceProvider) {
delete $httpProvider.defaults.headers.common['X-Requested-With'];
$locationProvider.html5Mode(false);
MockServiceProvider.enableMocks(true);
})
.provider('MockService',['$http', '$q', function ($http, $q) {
this.mocksEnabled = false;
this.enableMocks = function(val) {
mocksEnabled = val;
};
this.$get = function() {
var _mock_getNext = function() {
return {
'status' : {
'type': 'OK',
'msg': null
},
'data': {
'id': 123456789
}
};
};
return {
getData : function() {
if(mocksEnabled) {
return _mock_getNext;
} else {
return "Real Data";
}
}
};
};
}])
.controller('Main', function(MockService) {
$scope.maybe_mock_data = MockService.getData();
});
The $http and $q injections for the provider should be on the $get method of the provider, not on the constructor of the provider.
Fiddle: http://jsfiddle.net/pvtpenguin/UAP29/1/
.provider('MockService',function () {
this.mocksEnabled = false;
this.enableMocks = function(val) {
mocksEnabled = val;
};
this.$get = ['$http', '$q', function($http, $q) {
var _mock_getNext = function() {
return {
'status' : {
'type': 'OK',
'msg': null
},
'data': {
'id': 123456789
}
};
};
return {
getData : function() {
if(this.mocksEnabled) {
return _mock_getNext;
} else {
return "Real Data";
}
}
};
}];
})
Other minor problems:
$scope was not injected into the controller
In the getData function of the service, mocksEnabled needed to be this.mocksEnabled