Using a factory in AngularJS is it possible to change the TokenRestangular URL value.
for example could I do this:
.factory('projectFactory', ['TokenRestangular', function (TokenRestangular) {
var factory = {
projects: []
};
factory.get = function () {
return
resource = TokenRestangular.all('project');
resource.getList()
.then(function (project) {
factory.project = project;
return factory.project;
})
};
return factory;
}]);
and in my controller change the value of resource i.e.
var projects = projectFactory.get()
projects.TokenRestangular.all('a_different_url');
Hope that makes sense.
It's possible with a service but not with a factory. A service is created as a singleton so each time you inject it you will get the same instance. With a factory you will get a new one.
You should be able to have a simple service like the following and inject it into your controller:
myApp.service('SimpleService', function() {
this.localValue = 0;
this.setLocalValue = function(newValue) {
this.localValue = newValue;
}
});
Un-tested but should give you enough to go on!
Related
I am trying to pass a JSON string value that is stored in one controller to another. I am using a custom service to pass the data, but it doesn't seem to be passing the value.
The First controller where the JSON string value is stored:
filmApp.controller('SearchController',['$scope', '$http','$log','sharedService',function($scope,$http,$log,sharedService){
$scope.results = {
values: []
};
var vm = this;
vm.querySearch = querySearch;
vm.searchTextChange = searchTextChange;
vm.selectedItemChange = selectedItemChange;
function querySearch(query) {
return $http.get('https://api.themoviedb.org/3/search/movie?include_adult=false&page=1&primary_release_year=2017', {
params: {
'query': query,
'api_key': apiKey
}
}).then(function(response) {
var data = response.data.results.filter(function(obj) {
return obj.original_title.toLowerCase().indexOf(query) != -1;
})
return data;
for (var i = 0; i < data.results.length; i++) {
$scope.results.values.push({title: data.results[i].original_title});
// $log.info($scope.results.values);
}
return $scope.results.values;
})
};
function searchTextChange(text) {
// $log.info('Search Text changed to ' + text);
}
function selectedItemChange(item) {
$scope.value = JSON.stringify(item);
return sharedService.data($scope.value);
}
}]);
The custom Angular service - The value is received here:
filmApp.service('sharedService',function($log){
vm = this;
var value = [];
vm.data = function(value){
$log.info("getValue: " + value); // received value in log
return value;
}
});
The Second controller that wants to receive the JSON value from the First controller:
filmApp.controller('singleFilmController',['$scope', '$http','$log','sharedService',function($scope,$http,$log,sharedService){
var value = sharedService.data(value);
$log.info("Data: " + value);
}]);
The value is received in the service but the second controller can't seem to access it. Not sure why it is happening as I'm returning the value from the data() method from the service. Also, the selectedItemChange method is used by the md-autocomplete directive.
A good approach would be using a Factory/Service. take a look at this: Share data between AngularJS controllers
Technically, you can resolve this by simply changing your service definition to
(function () {
'use strict';
SharedService.$inject = ['$log'];
function SharedService($log) {
var service = this;
var value = [];
service.data = function (value) {
$log.info("getValue: " + value); // received value in log
service.value = value;
return service.value;
};
});
filmApp.service('SharedService', SharedService);
}());
But it is a very poor practice to inject $http directly into your controllers. Instead, you should have a search service that performs the queries and handle the caching of results in that service.
Here is what that would like
(function () {
'use strict';
search.$inject = ['$q', '$http'];
function search($q, $http) {
var cachedSearches = {};
var lastSearch;
return {
getLastSearch: function() {
return lastSearch;
},
get: function (query) {
var normalizedQuery = query && query.toLowerCase();
if (cachedSearches[normalizedQuery]) {
lastSearch = cachedSearches[normalizedQuery];
return $q.when(lastSearch);
}
return $http.get('https://api.themoviedb.org/3/search/movie?' +
'include_adult=false&page=1&primary_release_year=2017', {
params: {
query: query,
api_key: apiKey
}
}).then(function (response) {
var results = response.data.results.filter(function (result) {
return result.original_title.toLowerCase().indexOf(normalizedQuery) !== -1;
}).map(function (result) {
return result.original_title;
});
cachedSearches[normalizedQuery] = results;
lastSearch = results;
return results;
}
});
}
}
filmApp.factory('search', search);
SomeController.$inject = ['$scope', 'search'];
function SomeController($scope, search) {
$scope.results = [];
$scope.selectedItemChange = function (item) {
$scope.value = JSON.stringify(item);
return search.get($scope.value).then(function (results) {
$scope.results = results;
});
}
}
filmApp.controller('SomeController', SomeController);
}());
It is worth noting that a fully fledged solution would likely work a little differently. Namely it would likely incorporate ui-router making use of resolves to load the details based on the selected list item or, it could equally well be a hierarchy of element directives employing databinding to share a common object (nothing wrong with leveraging two-way-binding here).
It is also worth noting that if I were using a transpiler, such as TypeScript or Babel, the example code above would be much more succinct and readable.
I'm pretty new to AngularJS but I'm pretty sure all you are doing is two distinct function calls. The first controller passes in the proper value, the second one then overwrites that with either null or undefined
I usually use events that I manually fire and catch on my controllers. To fire to sibling controllers, use $rootScope.$emit()
In the other controller then, you would catch this event using a $rootscope.$on() call
This article helped me a decent amount when I was working on this in a project.
I have a controller, "ListController", which needs to be populated with server side data.
app.controller("ListController", function(){
var bar = this;
bar.venues = MyFactory.load();
}
and I wanted to get the json array from the server, so i was thinking to create a factory leveraging "$http" as such:
app.factory("MyFactory", ["$https", function($https){
var myService = {};
myService.load = function(){
$http.get("scripts/Query.php").success( function(rows){
myService.rows = rows;
return myService.rows;
};
};
return myService;
}]);
So, i was thinking that MyFactory would be able to be called from inside the app controller.
app is the same variable, of type: angular.module("BarMe", []);
The error i get in my javascript is: MyFactory is undefined
You didn't inject factory in your controller.
Try like this
app.controller("ListController", function(MyFactory){
}
More over your method has a callback direct assign won't bring you any data
Try like this
MyFactory.load().then(function(data){
bar.venues = data;
});
You also have to return $http with response from factory
myService.load = function(){
return $http.get("scripts/Query.php").success( function(rows){
return rows;
};
};
I need a service that provide me a scope or dynamic var , so I move on to other controllers.
I did a test on JSBin and is not working .
https://jsbin.com/semozuceka/edit?html,js,console,output
angular.module('app', [])
.controller('control1', function($scope, shared) {
shared.set('teste', {
testecontroller1: "Apenas um teste"
});
$scope.teste = shared.get();
$scope.teste2 = shared.get();
})
.controller('control2', function($scope, shared) {
$scope.teste = shared.get('teste');
shared.set('teste2', {
testecontroller2: "Apenas um teste"
});
$scope.teste2 = shared.get('teste2');
})
.service('shared', function($scope) {
$scope.data = {};
this.set = function(key, obj) {
$scope.data[key] = obj;
};
this.get = function(key) {
return $scope.data[key];
};
});
I would go for a factory service, since there is no need to create a custom one. Given the functionality of your controllers, I've created a simple factory, like so:
.factory('shared', function() {
var shared;
var data = {};
shared = {
set: setFunc,
get: getFunc
};
return shared;
function setFunc(key, input){
data[key] = input;
}
function getFunc(key){
if(key)
return data[key];
else return data;
}
})
The only part that might need clarification is the getFunc. In control1, you want to get the data object without specifying any properties. However, in control2 you do specify, which led to the conditional if(key). So to sum up, this function checks whether there is a passed attribute parameter and returns the appropriate data.
Here is a working plunker.
You can read more about the different Angular providers and the comparison between them in the official documentation.
Enjoy!
Do not try to use $scope, because it'll try to use the scopeProvider. You cannot inject it into a service. Also, the input for a service is an array (which contains a function), not just a function.
Having said that, you don't really need the scope at all, if you keep track of your variables inside your service.
.service('shared', [function() {
var data = {};
return {
set: function(v, val) {
data[v] = val;
},
get: function(v) {
return (v)? data[v]: data;
}
};
}]);
JSbin
I'm trying to create a provider to handle authentication in my app
function Authenticator($http) {
console.log($http);
return {
test: function() {}
}
}
app.provider('authenticator', function AuthenticatorProvider() {
this.config = function () {
var requestParams;
return {
setRequestParams: function (params) {
requestParams = params;
}
}
}();
this.$get = function($http) {
return new Authenticator($http);
};
});
When i run the code above $http is set as undefined. What am i doing wrong? What's the right way to inject $http service into a custom provider?
Thanks
I am guessing what you really want to be doing is something like this:
app.factory('AuthenticationService', ['$http', function($http) {
var AuthenticationService = function() {};
AuthenticationService.prototype.config = function)() { ... }
return new AuthenticationService();
}]);
This creates a service that can be injected into other controllers, directives and services, which there will only ever be a single shared instance of. Fetching the service by its string means the reference inside the function is local to the closure, which means the variable can be safely renamed, saving precious bandwidth.
I've got a factory which looks a little bit like this:
app.factory('MyFactory',['$http',function($http){
return {
state: {
collectionOfThings: {}
},
getThings: function() {
$http.get(url).success(function(data) {
this.state.collectionOfThings = data;
});
}
};
}]);
All it provides is a method which gets a thing from a web service, and I want to store the answer in state.collectionOfThings. However, when the $http success method is called, this no longer refers to the factory and refers to window. I would have thought this was quite a straightforward thing to do, but I can't figure it out.
How do I populate the field in the factory with the results from the $http.get?
app.factory('MyFactory',['$http',function($http){
var obj = {};
obj.state = {
collectionOfThings: {}
};
obj.getThings = function() {
$http.get(url).success(function(data) {
obj.state.collectionOfThings = data;
});
}
return obj;
}]);