AngularJS routing inside a factory - angularjs

I want to create a factory for routing purposes. I want to encapsulate this in a factory because I want to exchange info from one page to another. I don't know if this is the best practice. Please tell me if there are other better ways.
This is my controller:
angular.module('app.core')
.controller('mainCtrl', ['ShowService', 'ChangeViews', function(ShowService, ChangeViews){
var vm = this;
vm.namespaces = [];
vm.servers = [];
vm.p4path = '';
vm.gitpckname = '';
vm.server = '';
vm.ns = '';
ShowService.getNamespaces().then(function(response){
var data = angular.fromJson(response.data);
angular.forEach(data.namespaces, function(value){
vm.namespaces.push(value);
vm.initNamespaceSelVal = vm.namespaces[0];
vm.ns = vm.namespaces[0];
});
});
ShowService.getServers().then(function(response){
var data = angular.fromJson(response.data);
angular.forEach(data.servers, function(value){
vm.servers.push(value);
vm.initServerSelVal = vm.servers[0];
vm.server = vm.servers[0];
});
});
vm.doClick = function(value){
if(value){
var body = {};
body['server'] = vm.server;
body['p4path'] = vm.p4path;
body['packagename'] = vm.gitpckname;
body['namespace'] = vm.ns;
ShowService.getBraches(body).then(function(response){
console.log(response);
//$location.path('/hidden');
//ChangeViews.changeView('/hidden');
});
};
};
}]);
In the above code, I injected two custom made factories into controller. The "ShowService" works properly but the "ChangeViews" returns some errors.
Using $location service inside the controller(the commented line) works.
The factory code is:
angular
.module('app.services')
.constant('BASE_URL', 'http://localhost:8066')
.factory('ShowService', dataService)
.factory('ChangeViews', changeViews);
function dataService($http, BASE_URL){.....}
function changeViews($location, view){
var data = {
'changeView': changeView,
};
function changeView(view){
return $location.path(view);
};
return data;
}
The path to the html template is routed.
The error I'm receiving when injecting the ChangeViews factory is:
"Error: [$injector:unpr] http://errors.angularjs.org/1.5.5/$injector/unpr?p0=viewProvider%20%3C-%20view%20%3C-%20ChangeViews
What I'm missing?
Thank you

The problem is that you don't have injectable service named view, hence the unknown provider error.
Remove view from changeViews parameters list:
function changeViews($location) {
var data = {
changeView: changeView
};
function changeView(view) {
return $location.path(view);
};
return data;
}

Related

How to populate Angular controller variables from an array that is retrieved by $http.get

Using Angular 1.5.9 on frontend and WebAPI 2 on server. Calling a standard $http.get in the service to Get() method on controller. This is returning the ViewModel that I want to populate variables with in angular controller.
var carListController = function ($http, $scope, carService) {
var model = this;
model.carList = carService.getCarsByMake('Bentley', 10);
console.log(model.carList);
model.cars = model.carList[0].cars;
model.totalCars = model.carList[0].totalCars;
model.numberOfPages = model.carList[0].numberOfPages;
};
I get this error:
Cannot read property 'cars' of undefined
As you can see the console.log is showing the model.carList so I know issue is in controller code populating the other variables. What am I missing here? Any help appeciated.
Edit: carService
var cars = [];
var carService = function ($http) {
var getCarsByMake = function (make, size) {
$http.get('http://localhost:50604/api/cars?make=' + make + '&size=' + size)
.then(function (response) {
// Success
angular.copy(response.data, cars);
}, function () {
// Failure
});
return cars;
};
return {
getCarsByMake: getCarsByMake
};
};
You have to wrap your $scope variable population in a promise approach.
Since the model.carList data is not yet loaded when the population is happening, it's normal that the error arrises (Cannot read property 'cars' of undefined; meaning carList is undefined).
In your service carService.getCarsByMake you have to return a promise( $http.get method)
Only when the promise is resolved, you can populate your $scopevariables with this data.
var carListController = function ($http, $scope, carService) {
var model = this;
carService.getCarsByMake('Bentley', 10).then(function(response){
model.carList = response.data;
model.cars = model.carList.cars;
model.totalCars = model.carList.totalCars;
model.numberOfPages = model.carList.numberOfPages;
});
};
Return $http request on the service side :
var cars = [];
var carService = function ($http) {
var getCarsByMake = function (make, size) {
return $http.get('http://localhost:50604/api/cars?make=' + make + '&size=' + size);
};
return {
getCarsByMake: getCarsByMake
};
};

Angular 'this' doesn't assign value

I have the following code, and the problem is, that value fetched from json is not assigned to the vm variable
(function() {
angular
.module('app', [])
.controller('theController', theController);
function theController($http) {
var vm = this;
vm.message = [];
vm.message2 = [];
fetchJSON();
console.log(vm.message);
vm.message2 = vm.message;
function fetchJSON() {
$http
.get('http://beta.json-generator.com/api/json/get/4y2l2jq8l')
.success(function(data) {
vm.message = data;
});
}
}
})();
The value I assign to vm.message in fetchJson method doesn't appear in the main view, so when I set message2 = message it is still empty.
Live demo: http://codepen.io/matt23/pen/PZbNQa?editors=101
Have you tried setting the vm.message2 inside the fetchJSON function?
You are setting the vm.message2 right after fetchSON() hence the success message has not yet bene defined.
function fetchJSON() {
$http
.get('http://beta.json-generator.com/api/json/get/4y2l2jq8l')
.success(function(data) {
vm.message = data;
// HERE
});
}
or you can add another callback:
.complete(function() {
});

Passing arguments to factory

I am building an app using AngularJs.
I have a function (createStarMarkup) that returns a bunch of HTML based on a number.
function(rating) {
var rating = Number(rating);
var markup = "";
//Do some stuff
return markup;
}
I would like to be able to use this function multiple places in my application, so I defined it as a service in a Utility module.
var app = angular.module('utilities', []);
app.factory('createStarMarkup', function(rating) {
var rating = Number(rating);
var markup = "";
// Do some stuff
return markup;
});
I then add the 'utilities' module as a dependency to one of my other modules, and inject the service into the controller.
var app = angular.module('reviews', ['ionic', 'utilities']);
app.controller('reviewController',
['$scope', '$ionicActionSheet', 'createStarMarkup', function($scope, $ionicActionSheet, createStarMarkup){...});
This produces the following error
Error: [$injector:unpr] Unknown provider: $ratingProvider <- $rating <- createStarMarkup
The error goes away if I remove the rating parameter in the createStarMarkup function. Am I on the right track with using factory or should I look into something else?
Your factory definition is not valid. please change it as follows
app.factory('createStartupServices', ['', function() {
return {
getMarkup: function(rating) {
var rating = Number(rating);
var markup = "";
// Do some stuff
return markup;
},
}
}
]);
And your controller, you need to get the method getMarkup as follows
var app = angular.module('reviews', ['ionic', 'utilities']);
app.controller('reviewController',['$scope', '$ionicActionSheet', 'createStartupServices', function($scope, $ionicActionSheet, createStartupServices){
//createStartupServices.getMarkup(123);
});
The problem is here:
app.factory('createStarMarkup', function(rating) {
You are trying to inject a service called rating, that doesn't exist.
What are you trying to to is this:
app.factory('createStarMarkup', function() {
Service = {};
Service.myFunction = function(rating) {
var rating = Number(rating);
var markup = "";
// Do some stuff
return markup;
}
return Service;
});
In this way you can inject the createStarMarkup in any controller/directive/service and use the function like:
createStarMarkup.myFunction(rating);

Angularjs; use $http in service returns reference instead of actual data

I'm using the services directive in Angularjs not factory and I need to populate a json file to local variable;
/* Contains projects on the town */
leMaireServicess.service('cityService', function($http) {
// JSON regions and cities loader
this.cities = [];
// initCities
this.initCities = function() {
this.cities = $http.get('data/census/cities.js').success(function(data) {
return data;
});
return this.cities;
};
// Get city info
this.getCity = function() {
return this.cities;
};
});
And in my controller I have
// Saved game controller
leMaireControllers.controller('GameCoreCtrl', function($scope, cityService) {
/* Control the town project slides */
cityService.initCities();
$scope.city = cityService.getCity();
console.log($scope.city);
});
But instead of returning the actual data, it returns;
Object {then: function, catch: function, finally: function, success: function, error: function}
You can use a watch to make this work (see plunker)
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope,cityService) {
//$scope.cities = [];
$scope.service = cityService;
cityService.initCities();
$scope.$watch('service.getCity()', function(newVal) {
$scope.cities = newVal;
console.log(newVal)
});
});
app.service('cityService', function($http) {
var that = this;
this.cities = [];
this.initCities = function() {
$http.get('data.js').success(function(data) {
that.cities = data.cities;
});
};
this.getCity = function() {
return this.cities;
};
});
$http returns a promise which is what you're setting this.cities to.
This might help explain more,
https://stackoverflow.com/a/12513509/89702
In your controller you should be able to do something like this...
cityService.initCity().then(function(data) { $scope.city = data; }
You are working with promises which represent the result of an action that is performed asynchronously. Try it this way:
leMaireServicess.service('cityService', function($http) {
this.promise = {};
// initCities
this.initCities = function() {
this.promise = $http.get('data/census/cities.js');
};
// Get city info
this.getCity = function() {
return this.promise;
};
});
And in the controller you need to put your code in a callback:
// Saved game controller
leMaireControllers.controller('GameCoreCtrl', function($scope, cityService) {
/* Control the town project slides */
cityService.initCities();
cityService.getCity().then(function(result){
$scope.city = result.data;
console.log($scope.city);
});
});

Angular Factory Async Calls- Updating Controller?

I have a Controller and Factory to handle lists. The controller needs to get the lists loaded by the factory and display it in the view. I can't have a getLists() method in the factory because this needs to load asynchronously from FireBase. Here is my controller code-
angular.module('myApp.controllers', []).
controller('ListCtrl', ["$scope","listFactory", function($scope, ListFactory) {
$scope.lists = [];
$scope.$on("list_update", function(snapshot)
{
console.log(snapshot);
});
}]).
controller("EditListCtrl", ["$scope","listFactory", function($scope, ListFactory)
{
$scope.name = "";
$scope.items = [];
$scope.itemCount = 10;
$scope.save = function()
{
var List = {"items":[]};
for(var i = 0; i < $scope.itemCount; i++)
{
var item = $scope.items[i];
if(item != null)
{
List.items.push(item);
}
else
{
alert("Please fill all items of the list.");
return false;
}
ListFactory.putList(List);
$scope.items = [];
$scope.name = "";
}
}
}]);
The listFactory looks like this-
angular.module("myApp.factories", [])
.factory("listFactory", [function()
{
var lists = [{"name":"test"}];
var ListRef = new Firebase("https://listapp.firebaseio.com/");
var factory = {};
factory.getLists = function()
{
// this won't work
}
factory.putList = function(List)
{
ListRef.child("lists").push(List);
}
ListRef.on("child_added", function(snapshot)
{
// How do I get this back to the controller???
});
return factory;
}]);
The ListRef will dispatch a "child_added" event where the snapshot argument is has the list data. I need to get this back to the controller somehow. I'd like to do this with events but I'm not sure how to do that between the factory and the controller. I don't want to use the root scope because I think that's bad practice.
I'm new to this- any help would be appreciated!
Firstly update your list variable to have a container object:
var lists = { items: [{ name: 'test' }] };
Then expose access to the list through the factory, eg:
factory.getLists = function() {
return lists;
}
Then set a scope var in your controller:
$scope.lists = ListFactory.getLists();
Then whenever the child_added event is triggered, update the lists.items, and the $scope from the controller should reflect the changes.

Resources