How to combine two objects obtained with ngressource.
Each 5 seconds, i call my service to obtain a message and i want to add a new message with the olders.
My Json message :
[
{"age": 0,"id": "my first tweet","name": "Hello Sarah","snippet": "It's fabulous"},
{"age": 1,"id": "my second tweet","name": "Hello dude !","snippet": "It's fabulous"}
]
My Service :
'use strict';
/* Services */
var listlogServices = angular.module('listlogServices', ['ngResource']);
listlogServices.factory('Log', ['$resource',
function($resource){
return $resource('log/log1.json', {}, {
query: {method:'GET', params:{}, isArray:true}
});
}]);
My controller and functions
'use strict';
var app = angular.module('appRecupTweetApp');
app.controller('TimerCtrl1', function TimerCtrl1($scope, Timer){
$scope.$watch(function () { return Timer.data.myTab; },
function (value) {
$scope.data = value ;
//$scope.data.push(value);
//$scope.data = $scope.data.concat(value);
}
);
});
app.service('Timer', function ($timeout, Log) {
var data = { myTab: new Array()};
var updateTimer = function () {
data.myTab = Log.query();
$timeout(updateTimer, 5000);
};
updateTimer();
return {
data: data
};
});
I try to combine my object with 'push' and 'concat' but is not right.
Corrected error (Angular says : $scope.data is undefined )
Could i make this operation in my 'Timer' service or in my controller and what is the good solution.
Online demo : plnkr.co/edit/Vzdy9f7zUObd71Lm86Si
Thank's
Guillaume
You just have to initialize $scope.data in you TimerCtrl1 controller.
app.controller('TimerCtrl1', function TimerCtrl1($scope, Timer){
$scope.data=[];
$scope.$watch(function () { return Timer.data.myTab; },
function (value) {
$scope.data = value ;
//$scope.data.push(value);
//$scope.data = $scope.data.concat(value);
}
);
});
Related
I have an AngularJs application working with components and several modules. I created a plunker example to present my problem here.
I have my NavbarComponent where I declared my Controller where I inject my service called NavbarService.
In the NavbarService, I inject a factory resource to make my Rest call, once this call is made I'm trying to made some treatment on the response before returning it back to the controller, in this example I just apply a simple filter on it, but it doesn't work. If I omit my treatment and return only the categories, the code works and you can visualize a list of two.
I can make my treatment in the controller but this is a bad practice 'cause I believe it should be done in the Service, secondly since it's an asynchronous response I must do something like this to make it work, which is really really ugly:
navbarService.getCategories().$promise.then(function (response) {
console.log("controller", response[0].category);
vm.categories = categoryFilter(response[0].category);
}, function (error) {
console.log("an error occured");
});
Can someone please guide me through this, I'm out of solutions. Thank you
Another simple way is to pass a callback function to service from you component like this
'use strict';
angular.module('navbar').component('appNavbar', {
templateUrl: "navbar.template.html",
controller: [ 'navbarService', function appNavbarController(navbarService) {
var vm = this;
navbarService.getCategories(function(data){
// this will be called when service will get the response and filter function has filtered the response
vm.categories = data;
});
}]
});
Now service should be like this
'use strict';
angular.module('navbar').service('navbarService', ['categoryResourceService', 'categoryFilter', function(categoryResourceService, categoryFilter) {
var vm = this;
vm.getCategories = function(callback) {
categoryResourceService.query(function(response) {
console.log("[NavbarService] response:", response);
callback(categoryFilter(response));
}, function(error) {
console.log("[NavbarService] error:", error);
});
//return vm.categories;
}
}]);
Filter will be like this
'use strict';
angular.module('navbar').filter('category', function() {
return function(categories) {
var categoryIds = ['World'];
var result = [];
angular.forEach(categoryIds, function (categoryId) {
angular.forEach(categories, function (category) {
if (category.name == categoryId) {
console.log("Match");
result.push(category);
}
});
});
return result;
};
});
Your filter should be like this and it should be called in transformResponse in $resource query instead of service, i hope this will help you
'use strict';
angular.module('navbar').filter('category', function() {
return function(categories) {
var categoryIds = ['World'];
var result = [];
angular.forEach(categoryIds, function (categoryId) {
angular.forEach(categories, function (category) {
if (category.name == categoryId) {
console.log("Match");
result.push(category);
}
});
});
return result;
};
});
Your categoryResource.service should be like this
angular.module('shared').factory('categoryResourceService',
['$resource','categoryFilter', function($resource, categoryFilter) {
var provider = "categories.json";
var params = {
id: '#id'
};
return $resource(provider, params, {
query: {
isArray: true,
method: 'GET',
params: {},
transformResponse: function(categories) {
var results = categoryFilter(angular.fromJson(categories));
console.log("[categoryResourceService] filtered response:", results);
return results;
}
}
});
}]);
navbar.service should be like this simply
'use strict';
angular.module('navbar')
.service('navbarService', [ 'categoryResourceService', function (categoryResourceService) {
var vm = this;
vm.getCategories = function(){
vm.categories = categoryResourceService.query(function(response){
console.log("[NavbarService] response:", response);
}, function(error){
console.log("[NavbarService] error:", error);
});
return vm.categories;
}
}]);
And components like this
'use strict';
angular.module('navbar').component('appNavbar', {
templateUrl: "navbar.template.html",
controller: [ 'navbarService', function appNavbarController(navbarService) {
var vm = this;
vm.categories = navbarService.getCategories();
}]
});
I'm new to angularjs. In my webapp I'm trying to work with user contacts as follows.
SERVICE
app.service('Contacts', function ($http,$timeout,$q) {
return {
getData: function() {
var defer = $q.defer();
$http.get('../ListContacts')
.success(function(data) {
defer.resolve(data);
});
return defer.promise;
}
}
});
ContactsController, OtherControllers
$scope.contactsBook = {};
...
Contacts.getData().then(function(data) {
$scope.contactsBook = data;
});
I found the above method somewhere in SO itself. I used it because I don't want to use separate module for Contacts.
I can get data at page load. I can update my contacts at server through ajax posts (from ContactsController). Now I only need a way to update(/refresh) the list automatically in all controllers. How can I achieve that.
I found these three links related but being a newbie I'm unable to figure my way out.
While it is understandable that you may not want to update your current architecture, it may be necessary to adjust your calls slightly if you want to be able to easily share data between controllers via a service.
One flexible approach is to store the data in your service and register watchers in each controller. This allows you to call the service update from one controller (the Contacts controller) and have the change be reflected in all consuming controllers. Note the service is mocked.
You can find the working plunker example here.
Contacts Service:
var app = angular.module('app', []);
app.service('contactsService', function ($http) {
var contacts = [];
return {
loadData: function() {
var mockGet = $q.defer();
var data = [
{ id: 1, name: 'Jack' },
{ id: 2, name: 'Jill' }
];
contacts = data;
mockGet.resolve(contacts);
return mockGet.promise;
},
retrieveNewData: function() {
var mockGet = $q.defer();
var data = [
{ id: 1, name: 'Jack' },
{ id: 2, name: 'Jill' },
{ id: 3, name: 'Bob' },
{ id: 4, name: 'Susan' }
];
contacts = data;
mockGet.resolve(contacts);
return mockGet.promise;
},
getContacts: function () {
return contacts;
}
}
});
Contacts Controller:
app.controller('ContactsCtrl', ['$scope', 'contactsService',
function ($scope, contactsService) {
var vm = this;
vm.contacts = [];
vm.loadData = loadData;
vm.retrieveNewData = retrieveNewData;
$scope.$watch(angular.bind(contactsService, function () {
return contactsService.getContacts();
}), function (newVal) {
vm.contacts = newVal;
});
function loadData() {
contactsService.loadData();
}
function retrieveNewData() {
contactsService.retrieveNewData();
}
}
]);
Other Controller:
app.controller('OtherCtrl', ['$scope', 'contactsService',
function($scope, contactsService) {
var vm = this;
vm.contacts = [];
$scope.$watch(angular.bind(contactsService, function () {
return contactsService.getContacts();
}), function (newVal) {
vm.contacts = newVal;
});
}
]);
You can do
Contacts.getData().then(function(data) {
$scope.contactsBook = data;
$scope.$emit('contacts:updated', data);
});
And then, where you need to notify the controller about the update:
$rootScope.$on('contacts:updated', function(e, contacts) {
$scope.contacts = contacts;
});
Another approach
The service is holding the current contacts list
app.service('Contacts', function ($http,$timeout,$q) {
this.currentList = [];
this.getData = function() {
var defer = $q.defer();
$http.get('../ListContacts')
.success(function(data) {
defer.resolve(data);
});
return defer.promise;
}
});
In your controller:
Contacts.getData().then(function(data) {
$scope.contactsBook = data;
Contacts.currentList = data;
});
In other controller:
controller('AnotherController', function($scope, Contacts) {
$scope.contacts = Contacts.currentList;
});
If you are going to return an object literal you will need to turn your .service() into a .factory() module . In this case I'll be using a service module .
Example
Your service .
app.service('Contacts', function ($http,$timeout,$q) {
var Contacts = this;
contacts.getData = function() {
var defer = $q.defer();
$http.get('../ListContacts')
.success(function(data) {
defer.resolve(data);
});
return defer.promise;
}
}
return Contacts;
});
You will then need to inject this server into your ContactsController .
app.controller('ContactsController', function(Contacts){
$scope.data = null;
$scope.init = function(){
Contacts.getData().then(function(response){
$scope.data = response;
})
}
})
now data can be used in dom
Example
<li ng-repeat="x in data">{{x.name}}</li>
I am trying to create an Angular Factory, this is based on a example from a plural site course http://www.pluralsight.com/training/player?author=shawn-wildermuth&name=site-building-m7&mode=live&clip=3&course=site-building-bootstrap-angularjs-ef-azure.
From debugging the code in Chrome it appears to run fine. I can see when I debug it that the service gets my data and puts it in my array but when I look at the controller in either $scope.data or dataService.data the arrays are empty. I don't see any javascript errors. I'm not sure what I'm doing wrong, any suggestions. I'm using AngularJS v1.3.15.
module.factory("dataService", function($http,$routeParams,$q) {
var _data = [];
var _getData = function () {
var deferred = $q.defer();
$http.get("/api/v1/myAPI?mainType=" + $routeParams.mainType + "&subType=" + $routeParams.subType)
.then(function (result) {
angular.copy(result.data,_data);
deferred.resolve();
},
function () {
//Error
deferred.reject();
});
return deferred.promise;
};
return {
data: _data,
getData: _getData
};});
module.controller('dataController', ['$scope', '$http', '$routeParams', 'dataService',function ($scope, $http, $routeParams, dataService) {
$scope.data = dataService;
$scope.dataReturned = true;
$scope.isBusy = true;
dataService.getData().then(function () {
if (dataService.data == 0)
$scope.dataReturned = false;
},
function () {
//Error
alert("could not load data");
})
.then(function () {
$scope.isBusy = false;
})}]);
On
return {
data: _data,
getData: _getData
};});
you have "data: _data," while your array is named just "data". Change the name of the variable to match and it will work:
var _data = [];
Why would you use deferred from $q this way?
The proper way to use $q:
$http.get("/api/v1/myAPI?mainType=" + $routeParams.mainType + "&subType=" + $routeParams.subType)
.success(function (result) {
deferred.resolve(result);
}).error(
function () {
//Error
deferred.reject();
});
And then in controller
dataService
.getData()
.then(function success(result) {
$scope.data = result; //assing retrived data to scope variable
},
function error() {
//Error
alert("could not load data");
});
In fact, there are some errors in your codes :
In your Service, you define var data = [];, but you return data: _data,. So you should correct the defination to var _data = []
you don't define _bling, but you use angular.copy(result.data,_bling);
One more question, why do you assigne the service to $scope.data : $scope.data = dataService ?
EDIT :
Notice that there 3 changes in the following codes:
comment the $scope.data = dataService;, because it makes no sense, and I think that $scope.data should be the data that the service returns.
$scope.data = dataService.data;, as I described in 1st point. You can see the result from the console.
In the if condition, I think that you want to compare the length of the returned data array, but not the data.
module.controller('dataController', ['$scope', '$http', '$routeParams', 'dataService',function ($scope, $http, $routeParams, dataService) {
// $scope.data = dataService;
$scope.dataReturned = true;
$scope.isBusy = true;
dataService.getData().then(function () {
if (dataService.data.length === 0){
$scope.dataReturned = false;
}else{
$scope.data = dataService.data;
console.log($scope.data);
}
},
// other codes...
})}]);
I am trying to reuse a few bigger functions over 3 controllers in Angular JS. I don't want to pin the functions to my root scope as I want to keep it clear of functions which will be used only 3 times within those 3 controllers.
angular.module('adminModule', ['adminDependency'])
.controller('ctrl1', ['$scope', 'details', function ($scope, details) {
// use functions
}])
.controller('ctrl2', ['$scope', 'details', function ($scope, details) {
// use functions
}])
.controller('ctrl3', ['$scope', 'details', function ($scope, details) {
// use functions
}])
Can you tell me how i can achieve that without writing my functions into the root scope?
Tried it inside a factory but calling AdminModule.toLevelKey() wont work...
.factory('AdminModule',
[ '$resource', 'serviceURL', function ($resource, serviceURL) {
return $resource(serviceURL + 'class/:id', {
id : '#id'
}, {
getClasses : {
method : 'GET',
url : serviceURL + 'extended/class',
isArray : true
},
toLevelKey : function (value) {
var return_key = parseInt(Math.floor(value / 3));
var return_level = value % 3;
return { level : return_level + 1, levelTranslationKey : return_key + 1 };
},
fromLevelKey : function (level, key) {
if (angular.isDefined(level)) {
var value = (key - 1) * 3 + (level - 1);
return value;
} else {
return null;
}
}
}
);
} ]);
This can be done by a service:
.service('myService', function(){
return {
fn: function(){
// do what you want
}
}
});
usage:
.controller('ctrl2', ['$scope', 'details', 'myService',
function ($scope, details, myService) {
// use functions
myService.fn();
}])
In accordance with the above comment of David FariƱa: "Are there even more options?".
Except executing, you also can pass data from one controller to another and broadcast event, when it happens.
SharedService:
angular.module("yourAppName", []).factory("mySharedService", function($rootScope){
var mySharedService = {};
mySharedService.values = {};
mySharedService.setValues = function(params){
mySharedService.values = params;
$rootScope.$broadcast('dataPassed');
}
return mySharedService;
});
FirstController:
function FirstCtrl($scope, mySharedService) {
$scope.passDataInSharedSevice = function(params){
mySharedService.setValues(params);
}
}
SecondController:
function SecondController($scope, mySharedService) {
$scope.$on('dataPassed', function () {
$scope.newItems = mySharedService.values;
});
}
I'm trying to play with angularJS.
I wrote this easy example :
var myApp = angular.module('myApp',[]);
myApp.factory( 'Data' , function() {
return { message: "I'm data from a service" }
});
function FirstCtrl($scope) {
$scope.data = Data;
}
function SecondCtrl($scope) {
$scope.data = Data;
}
but i get the following error message:
ReferenceError: Data is not defined
What am i doing wrong
You're using Data which you never defined in the global scope.
Instead, since you defined it with Angular's dependency injection mechanism:
var myApp = angular.module('myApp',[]);
myApp.factory( 'Data' , function() {
return { message: "I'm data from a service" }
});
// angular will figure it out based on parameter name
myApp.controller("FirstCtrl",function($scope,Data) {
$scope.data = Data;
});
fiddle
var myApp = angular.module('myApp',[]);
myApp.factory( 'Data' , function() {
return { message: "I'm data from a service" }
});