I am making a website based on MEAN. Now I am trying to pass data from one controller to the next, but I don't seem to get it done. When an option is selected I want to take this value to the next page
This is the page with the selectbox:
<div class="plumber-by-city col-sm-12 home-text-col" ng-controller="DataCtrl">
<div class="title-1">Search by cityname</div>
<select ng-model="selectedItem" ng-change="change()" ng-options="item as item.city for item in items"></select><span class="fa fa-caret-down"></span>
</div>
On change I want to take the selectedItem passed through to the next page with DataCtrl2
This is my DataCtrl:
app.controller('DataCtrl', function($scope,$http,getData,$location,$routeParams){
getData.getCity($scope);
$scope.change = function() {
$location.path('/plumber-in/' + $scope.selectedItem.city);
};
});
And the service that retrieves data from DB:
app.factory('getData', function($http){
return {
getCity: function($scope){
return $http.get("/getdata").then(function(response){
$scope.items = response.data;
$scope.selectedItem = response.data[0];
});
}
};
});
Now I don't know what to put in the DataCtrl2 for the second page and how to use the data from the DataCtrl in this page
What you need is a Setter and Getter Method in your service. Something like this
app.controller('DataCtrl',
function($scope,$http,getData,$location,$routeParams){
getData.getCity().then(function(response) {
$scope.items = response.data;
$scope.selectedItem = response.data[0];
});
$scope.change = function() {
// sets the data to the service
getData.setItem($scope.selectedItem);
$location.path('/plumber-in/' + $scope.selectedItem.city);
};
});
app.factory('getData', function($http){
return {
getCity: function(){
return $http.get("/getdata");
},
setItem: function(item) {
this.item = item;
},
getItem: function() {
return this.item;
}
};
});
app.controller('DataCtrl2',
function($scope, $http, getData,$location,$routeParams){
// get the data from the service
getData.getItem();
});
don't use $scope inside the factory. just return the request-promise to the controller and do your logic in there.
app.factory('getData', function($http){
return {
getCity: function(){
return $http.get("/getdata");
}
};
});
modify the controller like this
app.controller('DataCtrl', function($scope,$http,getData,$location,$routeParams){
getData.getCity().then(function(response) {
$scope.items = response.data;
$scope.selectedItem = response.data[0];
});
$scope.change = function() {
$location.path('/plumber-in/' + $scope.selectedItem.city);
};
});
Related
I'm trying get data from db to UI. Url given via provider is getting the data.
Controller in controller DetailsProvider.getDashboardDetails() is getting null.
var appmod = angular.module('project.DetailDashboardController', []);
appmod.controller("DetailDashboardController", ['$rootScope', '$scope', '$state', 'DetailsProvider',function($rootScope, $scope, $state,DetailsProvider) {
console.log("DetailDashboardController --- ");
$scope.DetList= DetailsProvider.getDashboardDetails()
}]);
})(window, window.angular);
provider which will call the list
(function(angular) {
var appmod = angular.module('project.DetailsServiceProvider', []);
appmod.provider('DetailsProvider', function() {
this.$get = ['_$rest', function DetailServiceFactory(_$rest) {
return new DetailsProvider(_$rest);
}];
});
function DetailsProvider(_$rest) {
this._$rest = _$rest,
this.getDashboardDetails = function(_callback, _data) {
var newData = null;
_$rest.post({
url: window.localStorage.getItem('contextPath') +'home/listdetail',
data: {} ,
onSuccess:_callback
}
});
}
};
})(window.angular);
Thanks in advance for any kind of reply!
You should return promise from your service method and do thenable in your controller.
Root Cause : your are returning the newData which will initalized later after completing the ajax call.Before completing it,you are returning the same variable which will be always null.
In provider,
(function(angular) {
var appmod = angular.module('project.DetailsServiceProvider', []);
appmod.provider('DetailsProvider', function() {
this.$get = ['_$rest', function DetailServiceFactory(_$rest) {
return new DetailsProvider(_$rest);
}];
});
function DetailsProvider(_$rest) {
this._$rest = _$rest,
this.getDashboardDetails = function(_callback, _data) {
var newData = null;
_$rest.post({
url: window.localStorage.getItem('contextPath') +'home/listdetail',
data: {} ,
onSuccess:_callback
}
});
}
};
})(window.angular);
and in controller,
$scope.list = function() {
DetailsService.getDashboardDetails(function(data){
varr holdIt = data.data.DList;
});
};
I have an AngularJS application (1.4.10) and I need to share some data between two controllers.
So I made my factory:
.factory('CardsForService', function($http, URL){
var service = {
"block_id": '',
"service_id": ''
};
service.save_data = function(block_id, service_id){
service.block_id = block_id;
service.service_id = service_id;
};
service.get_data = function(){
return service;
};
return service;
})
I insert the data in the first controller:
$scope.open = function(id, type){
console.log(id +" "+type);
CardsForService.save_data(id, type);
...
And I try to get the data in another controller, like this:
$scope.$on('$routeChangeSuccess', function() {
if (algo_to_used == "service"){
var data = CardsForService.get_data();
console.log(data);
} else {
}
});
The console.log output this:
Object {block_id: "", service_id: ""}
If I try the same get_data() function in the same controller where I call the save_data() function I have the correct results.
What am I missing?
Change Factory Like this
app.factory('CardsForService', function(){
var service = {
"block_id": '',
"service_id": ''
};
var save_data = function(block_id, service_id){
service.block_id = block_id;
service.service_id = service_id;
};
var get_data = function(){
return service;
};
return{
saveData:save_data,
getData:get_data
}});
And in controllers
app.controller('FirstCtrl',function(CardsForService){
CardsForService.setData(id, type);
});
app.controller('SecondCtrl', function($scope, CardsForService){
$scope.data = CardsForService.getData();
});
This sounds like it could be a timing issue. Data from a service like this isn't reactive. Here's a snippet that should help visualize it.
var app = angular.module("demo", []);
app.factory("MySvc", function() {
var data = {};
data.setData = function(key, value) {
this[key] = value;
}
data.getData = function(key, def) {
return key in this ? this[key] : def;
};
return data;
});
app.controller("test1", ["$scope", "MySvc", "$timeout",
function($scope, MySvc, $timeout) {
$timeout(100).then(function() {
MySvc.setData("foo", "bar");
$scope.data = MySvc.getData("foo");
});
}
]);
app.controller("test2", ["$scope", "MySvc", "$timeout",
function($scope, MySvc, $timeout) {
$timeout(500).then(function() {
$scope.data = MySvc.getData("foo", "baz");
});
}
]);
app.controller("test3", ["$scope", "MySvc",
function($scope, MySvc) {
$scope.data = MySvc.getData("foo", "asdf");
}
]);
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js "></script>
<div ng-app="demo">
<pre ng-controller="test1">Test 1: {{ data }}</pre>
<pre ng-controller="test2">Test 2: {{ data }}</pre>
<pre ng-controller="test3">Test 3: {{ data }}</pre>
</div>
Ok I solved the problem. Basically before I was using this code for the redirect to the new page:
$window.location.assign('/cards/service');
And now I switched to this code:
$location.path('/cards/service');
And it's working.
The only thing is that when it wasn't working when I redirect the page the console in the chrome inspector refresh for every reloading, now the console do not refresh. Can someone tell me the difference between those two functions?
I am wondering about the best way to structure the services / factories in an Angular app to consume a REST API. I know about $resource but I don't want to use it since my API is a bit special and not just CRUD on /api/resource/:id etc.
There are two basic ways I can think of and I'm not sure which is the better once. I guess there are up- and downsides for both and that's why I'm asking.
Option 1
Have an API factory with many methods for each model. That would look something like this:
angular.module('myApp', ['$http'])
.factory('apiService', function() {
var o = {
posts: [],
comments: []
};
o.getAllPosts = function() {
return $http.get('/api/v1/posts').success(function(data){
angular.copy(data, o.posts);
});
};
o.getAllComments = function() {
return $http.get('/api/v1/comments').success(function(data){
angular.copy(data, o.comments);
});
};
})
.controller('MainCtrl', function($scope, apiService) {
// Get all posts
$scope.posts = apiService.getAllPosts();
// Get all comments
$scope.comments = apiService.getAllComments();
});
Option 2
Have a factory for every data model. Something like this:
myModule.factory('posts', ['$http', function($http){
var o = {
posts: [],
post: {}
};
o.getAll = function() {
return $http.get('/api/v1/posts').success(function(data){
angular.copy(data, o.posts);
});
};
o.getOne = function(params) {
return $http.get('/api/v1/posts/'+params.hash_id).success(function(data){
angular.copy(data, o.post);
});
};
o.create = function(post) {
return $http.post('/api/v1/posts', post).success(function(data){
o.posts.unshift(data);
});
};
return o;
}]);
.controller('MainCtrl', function($scope, posts) {
// Get all posts
$scope.posts = posts.getAll();
});
What is the better way to handle this and why?
I am trying to use promise and service to set the data from http request.
I have something like this
angular.module('myApp').controller('productController', ['$scope', 'testService',
function($scope, testService) {
testService.getProducts().then(function(products){
console.log(products);
})
//getFirstProduct is trigger by ng-click user action.
$scope.getFirstProduct = function(){
var t = testService.getFirstProduct();
console.log(t);
}
}
]);
angular.module('myApp').service('testService', ['Product', '$q',
function(Product, $q) {
var products, firstProduct;
var getFirstProduct = function(){
return firstProduct;
}
var setFirstProduct = function(product) {
firstProduct = product;
}
var getProducts = function() {
var deferred = $q.defer();
//Product is a $resource object to send an http request
Product.query({
id: 123
}, function(result) {
setFirstProduct(result.first);
deferred.resolve(classes);
});
return deferred.promise;
}
return {
setFirstProduct: setFirstProduct,
getProducts: getProducts,
getFirstProduct: getFirstProduct
};
}
]);
I need to be able to get First product but I am not sure how to fix this. Can anyone help me about it? Thanks a lot
I see a number of errors in the code such as missing semicolons, mistyped variable/function names, and that setProducts was clobbering its variable.
Also, added $q, as mentioned by #manube
The following should work better:
angular.module('myApp').controller('productController', ['$scope', 'testService',
function($scope, testService) {
testService.getProducts().then(function(products){
console.log(products);
})
//getFirstProduct is trigger by ng-click user action.
$scope.getFirstProduct = function(){
var t = testService.getFirstProduct();
console.log(t);
}
}
]);
angular.module('myApp').service('testService', ['Product', '$q',
function(Product, $q) {
var products, firstProduct;
var getFirstProduct = function(){
return firstProduct;
}
var setFirstProduct = function(product) {
firstProduct = product;
}
var getProducts = function() {
var deferred = $q.defer();
//Product is a $resource object to send an http request
Product.query({
id: 123
}, function(result) {
setFirstProduct(result.first);
deferred.resolve(classes);
});
return deferred.promise;
}
return {
setFirstProduct: setFirstProduct,
getProducts: getProducts,
getFirstProduct: getFirstProduct
};
}
]);
I have a service which will make a call to the server and returns the data. I am binding service to a variable on scope.
Example:
Let the service be DataModelService
in the controller : $scope.data = DataModelService
in the view <div ng-repeat="value in data.persons">{{value.name}}</div>
My Code :
This is how my code looks like:
/**DataModelService**/
factory('DataModelService', [
'DataService',
function (DataService) {
var service;
service = {
changeState: function (params) {
DataService.changePersonState(params)
.then(function (response) {
service.loadData(response.data);
});
},
loadData: function (responseData) {
service.persons = responseData.persons;
}
}
return service;
}
]);
/**DataService**/
factory('DataService', ['$http',
function ($http) {
return {
changePersonState: function (params) {
return $http.post("url", params);
}
}
}
]);
/**DataController**/
.controller('DataController', ['DataModelService',
function (DataModelService) {
$scope.data = DataModelService;
}
]);
/view/
<div ng-repeat = "person in data.persons" >{{person.name}} </div>
On the view I am doing a ng-repeat on a key in data i.e. ng-repeat="value in data.persons"
and also I have an option to change the state of person to active or inactive, so whenver i make a change to the state of the person, a call is sent to the server and data is set into the Service and as it is binded to the view, it should automatically update the data. But whats happening in my case, ng-repeat is not removing old data and instead it is appending new data to the old data.
For me its not good approach to write promise callback (then) into service. Because in your case, DataModelService returns data with some delay but not promise. And we don't know when.
So the way to make it work to add basic $timeout and fetch data from service by using other method.
So my suggestion is Demo
and your fixed example: Demo2
If we will take your example, it should be like:
JS
var fessmodule = angular.module('myModule', ['ngResource']);
fessmodule.controller('fessCntrl', function ($scope, DataModelService, $timeout) {
$scope.alertSwap = function () {
DataModelService.changeState('ff');
$timeout(function(){
$scope.data = DataModelService.getResponse();
}, 10);
}
});
fessmodule.$inject = ['$scope', 'Data', '$timeout'];
/**DataModelService**/
fessmodule.factory('DataModelService', [ 'DataService',function (DataService) {
var value = [];
var service = {
changeState: function (params) {
DataService.changePersonState(params)
.then(function (response) {
value = response.persons;
});
},
getResponse : function(){
return value;
}
}
return service;
}
]);
/**DataService**/
fessmodule.factory('DataService', ['$q',function ($q) {
var data = { // dummy
persons: [{
name: "Bob"
}, {
name: "Mark"
}, {
name: "Kelly"
}]
};
var factory = {
changePersonState: function (selectedSubject) {
var deferred = $q.defer();
deferred.resolve(data);
return deferred.promise;
}
}
return factory;
} //function
]);