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
Related
app.controller('AdminUserCtrl', function ($scope, $controller, $location, $http, $rootScope, $pouchDB, $state, $stateParams) {
$controller('AdminCtrl', {$scope: $scope});
console.log("AdminUser Controller reporting for duty.");
$scope.items = {};
$pouchDB.startListening();
// try to call
$pouchDB.getUsers();
console.log($pouchDB.getUsers());
// Listen for changes which include create or update events
$rootScope.$on("$pouchDB:change", function (event, data) {
$scope.items[data.doc._id] = data.doc;
$scope.$apply();
});
// Listen for changes which include only delete events
$rootScope.$on("$pouchDB:delete", function (event, data) {
delete $scope.items[data.doc._id];
$scope.$apply();
});
// Look up a document if we landed in the info screen for editing a document
if ($stateParams.documentId) {
$pouchDB.get($stateParams.documentId).then(function (result) {
$scope.inputForm = result;
});
}
app.service("$pouchDB", ["$rootScope", "$q", function ($rootScope, $q) {
var database;
var changeListener;
this.setDatabase = function (databaseName) {
database = new PouchDB(databaseName);
};
this.getUsers = function () {
return database.query({
map: function (doc, emit) {
if (doc.type === "user") {
emit(doc._id, doc);
}
}
});
};
this.startListening = function () {
changeListener = database.changes({
live: true,
include_docs: true
}).on("change", function (change) {
if (!change.deleted) {
$rootScope.$broadcast("$pouchDB:change", change);
} else {
$rootScope.$broadcast("$pouchDB:delete", change);
}
});
};
I trying to create view / query db ... but nothing happens ...
Can anyone provide example how to create view in angularjs-pouchdb ?
console.log($pouchDB.getUsers());
return:
Promise {[[PromiseStatus]]: "pending", [[PromiseValue]]: undefined}
Follow the docs, you want something that looks like . . .
app.service("$pouchDB", ["$rootScope", "$q", function ($rootScope, $q) {
var instance = {};
instance.database = null;
instance.changeListener = null;
instance.setDatabase = function (databaseName) {
this.database = new PouchDB(databaseName);
};
instance.getUsers = function () {
return this.database.query({
map: function (doc, emit) {
if (doc.type === "user") {
emit(doc._id, doc);
}
}
});
};
instance.startListening = function () {
this.changeListener = this.database.changes({
live: true,
include_docs: true
}).on("change", function (change) {
if (!change.deleted) {
$rootScope.$broadcast("$pouchDB:change", change);
} else {
$rootScope.$broadcast("$pouchDB:delete", change);
}
});
};
return instance;
}]);
I am having a controller and service like below
(function () {
var mockController = function ($scope, MockService) {
$scope.message = "This is a text message";
$scope.getCities = function () {
$scope.places = [];
MockService.getCities().then(function (response) {
var places = response.data["weather-app:root"].city;
if (places) {
if (Array.isArray(places)) {
$scope.places = places;
} else {
$scope.places.push(places);
}
}
});
};
};
var mockService = function ($http) {
this.getCities = function () {
return $http.get("../rest/url", {
headers: {
'Accept': 'application/yang.data+json'
}
});
};
};
angular.module("MockApp", [])
.service("MockService", mockService)
.controller("MockController", mockController);
}())
I created a mock service like below for mocking the service for unit testing.
(function () {
angular.module('mock.service', [])
.service('MockService', function ($q) {
var mockService = {};
mockService.getCities = function () {
var mydata = {
"weather-app:root": {
"city": [
{
"city-name": "Chennai"
, "country-name": "India"
}
, {
"city-name": "Mangalore"
, "country-name": "India"
}
]
}
}
return $q.when(mydata);
};
return mockService;
});
}());
My test case is like
describe("MockController", function () {
var $scope;
beforeEach(function () {
module("MockApp");
beforeEach(module('mock.service'));
inject(function (_$controller_, _$rootScope_, _MockService_) {
$scope = _$rootScope_.$new();
controller = _$controller_("MockController", {
$scope: $scope
, MockService: _MockService_
});
});
});
describe("Test", function () {
it("Should be Bangalore", function () {
$scope.getCities();
console.log($scope.places);
});
});
});
the problem is that the then method in controller is not getting called. How can I resolve the issue ?
Three things to fix...
Don't nest the beforeEach calls. You can init multiple modules with module.
beforeEach(function() {
module('MockApp', 'mock.service');
// and so on
Your mock data does not quite match what you'd see from an $http based promise response
return $q.when({data: mydata});
In order to process promises, you need to trigger a digest cycle
it("Should be Bangalore", function() {
$scope.getCities();
$scope.$apply();
console.log($scope.places);
});
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;
}]);
I've refactored my code so that all model creation is off the controller and inside my factory. This works great but now I want to make sure that on init that all my promises are resolved in order and so attempting to use $q.all returns an array of undefined items. What am I doing wrong? Here is my code:
//Data 1
{'name': 'a name'}
//Data 2
{'city': 'a city'}
//Data 3
{'car' : 'a car'}
var app = angular.module('app', []);
app.service('myHttpService', ['$http', '$q', function($http, $q){
var DEFAULT_ERROR = "An error occurred while contacting the server.";
return {
myPromise : function(httpAction){
var deferred = $q.defer();
httpAction.success(function(data){
deferred.resolve(data);
}).error(function(reason){
if(reason) {
if(typeof reason === 'object' && reason.err)
deferred.reject(reason.err);
else if(typeof reason === 'string')
deferred.reject(reason);
else
deferred.reject(DEFAULT_ERROR);
}
else
deferred.reject(DEFAULT_ERROR);
});
return deferred.promise;
}
}
}]);
app.factory('myService', function($http, $q, myHttpService) {
return MyData = {
getData1: getData1,
getData2: getData2,
getData3: getData3,
getAllData: getAllData
};
function getData1() {
return myHttpService.apiPromise($http.get('/api/data_1')).then(function(data1){
MyData.data1 = data1;
});
}
function getData2() {
return myHttpService.apiPromise($http.get('/api/data_2')).then(function(data2) {
MyData.data2 = data2;
});
}
function getData3(){
return myHttpService.apiPromise($http.get('/api/data_3')).then(function(data3) {
MyData.data3 = data3
});
}
function getAllData(promises) {
return $q.all(promises).then(function(data) {
MyData.allData = data;
})
}
});
app.controller('MyCtrl', function (myService) {
var this = self;
this.data1 = myService.getData1;
this.data2 = myService.getData2;
this.data3 = myService.getData3;
this.allData = myService.getAllData;
this.init = function() {
//HOW DO I GET THIS
myService.getData1().then() {
self.data1 = myService.data1;
myService.getData2().then() {
self.data2 = myService.data2;
myService.getData3().then {
self.data3 = myService.data3;
}
}
}
// INTO THIS??
myService.getAllData([myService.getData1(), myService.getData2(), myService.getData3()]).then(function() {
self.allData = myService.getAllData;
console.log(self.allData);
//EXPECT [{'name': 'my name'},{'city': 'my city'},{'car' : 'my car'}]
//INSTEAD GET
//[undefined, undefined, undefined]
})
}
});
In your case myService.getDataN() is not a promise. Every getDataN should also return data inside then.
...
function getData1() {
return myHttpService.apiPromise($http.get('/api/data_1')).then(function(data1){
MyData.data1 = data1;
return data1;
});
}
...
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++;
});
};
}]);