Problems trying to define and configure my custom provider - angularjs

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

I trying to create view / query db ... but nothing happens ...

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;
}]);

How to test Angular controller having a service

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);
});

Save wrong data in controller (AngularJS)

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;
}]);

AngularJS $q.all how to resolve data in service and not in controller

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;
});
}
...

Promises and Syncing the View and Model in Angular

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++;
});
};
}]);

Resources