Accessing a dictionary from angular controller - javascript

I'm trying to do the following.
Angular controller calls and MVC controller GET method. This method then calls into a REST API on the web which returns a list of configuration items. I then turn this into a dictionary so I can look up configuration values based on the key, and then I want to pass this back to the Angular controller and store it there in a variable that I can access from many different scenarios, eg displaying them in grids, updating values, changing and updating them back to the REST API etc. I have tried to set up the pipes but I can't seem to get the data in a readable/usable format in the Angular controller.
My controller
app.controller("SEFlexHomeController", ["$scope", "$http", "$modal", "$log", "$element", "$rootScope", "AlertsService", "AuthService", "SEApplicationService", function ($scope, $http, $modal, $log, $element, $rootScope, AlertsService, AuthService, SEApplicationService) {
$rootScope.closeAlert = AlertsService.closeAlert;
$scope.isDataLoading = false;
$scope.AuthService = AuthService;
$scope.configvalues = angular.fromJson(SEApplicationService.getCloudConfigParams());
}
]);
My Angular Service
app.factory("SEApplicationService", ["$log", "$http", "$timeout", function($log, $http, $timeout) {
var appService = {};
appService.getCloudConfigParams = function () {
return $http.get("/SEFlex/SEFlexAdmin/GetCloudConfigValues");
}
return appService;
}]);
My MVC controller
public ActionResult GetCloudConfigValues()
{
try
{
var helper = new ApplicationServiceHelper();
var dictionary = helper.GetCloudConfigValues()
.ToList()
.ToDictionary(item => item.ConfigKey, item => item.ConfigValue);
var returnData = JsonConvert.SerializeObject(dictionary);
return Json(new
{
success = true,
data = returnData
}, JsonRequestBehavior.AllowGet);
}
catch (Exception exception)
{
return Json(new
{
success = false,
errors = new[] { exception.Message }
});
}
}
I can confirm at the time of creating the Dictionary in the MVC controller, the dictionary looks as expected for a .NET dictionary. What do I need to do to convert this either before transmission back or back in Angular, so that I can access it in angular as
$scope.configvalues["keyName"]

The $http.get() call returns a promise. You should change the
$scope.configvalues = angular.fromJson(SEApplicationService.getCloudConfigParams());
to
SEApplicationService.getCloudConfigParams().then(function(config) {
$scope.configvalues = config;
});

Related

error msg - is not a function when using prototype for an Angular service

I am building an Angular service for some re-usable code for an upload named 'UploadService' which gets called within a controller below - even though the service has been loaded in I always get the following error
`UploadService.upload is not a function at h.$scope.uploadImage...)`
My Upload Service (UploadService.js)
abcdServices.service('UploadService', function(ApiService, $http, $localStorage, $location, $timeout, $q, $rootScope, Upload) {
var UploadService = function() {
this.upload_in_progress = false;
this.attached_media = {
photos: [],
videos: []
}
};
UploadService.prototype.upload = function(files) {
console.log('get here');
};
return UploadService;
});
// My Controller where the service is called - note I have added this to the
$scope.uploadImage = function(files, fileIndex, imageIndex) {
console.log('existing upload image');
console.log(files); // this shows an array in the console log as expected
UploadService.prototype.upload(files);
}
// The controller has the service loaded in at the top and I have included UserService.js file in the index.php
abcdControllers.controller('PostController', function( $http, $rootScope, UploadService) {
The prototype is just a javascript way to add instance members to a "Class". The point is, you have to use the UploadService.upload() directly not through the prototype UploadService.prototype.upload() because UploadService is not a reference to the class, angularjs' injector gives you an instance of that class, when you declare a service UploadService, angularjs injects a singleton reference to new UploadService().
Also, you are declaring the service class in the wrong way, your approach doesn't return the UploadService class for the injector, it only returns a function that returns the UploadService, which is never exposed. A better approach for that would be something like the code bellow:
abcdServices.service('UploadService', function UploadService(ApiService, $http, $localStorage, $location, $timeout, $q, $rootScope, Upload) {
this.upload_in_progress = false;
this.attached_media = {
photos: [],
videos: []
};
this.upload = function(files) {
console.log('get here');
};
});
Or you can simply change it to a factory provider and return a new instance of your "Class":
abcdServices.factory('UploadService', function(ApiService, $http, $localStorage, $location, $timeout, $q, $rootScope, Upload) {
var UploadService = function() {
this.upload_in_progress = false;
this.attached_media = {
photos: [],
videos: []
};
};
UploadService.prototype.upload = function(files) {
console.log('get here');
};
return new UploadService();
});

Using $http as a function parameter - AngularJS

I'm trying to use this AngularJS material chip.
(CONTACT CHIP - With auto-complete)
https://material.angularjs.org/latest/demo/chips
And it has a different structure of what I'm used to. I want to adapt to get the contacts from my mongodb with $http, like:
$http.get("/contacts").success(function(response) {
contacts = response;
});
But in their Angular Material code example is like this:
angular.module('MyApp',['ngMaterial', 'ngMessages', 'material.svgAssetsCache'])
.controller('ContactChipDemoCtrl', DemoCtrl);
function DemoCtrl ($q, $timeout) {
...
function loadContacts() {
var contacts = [
'Marina Augustine',
'Oddr Sarno',
'Nick Giannopoulos',
'Narayana Garner',
'Anita Gros',
'Megan Smith',
'Tsvetko Metzger',
'Hector Simek',
'Some-guy withalongalastaname'
];
}
...
How can I use $http as a parameter for the DemoCtrl function? To get the contacts from db
MyModule.controller("DemoController", DemoCtrl);
DemoCtrl.$inject = ['$http'];
function DemoCtrl ($http) {
$http.get("/contacts").success(function(response) {
contacts = response;
});
Above is the preferred way to setup a controller because it doesn't use an anonymous function rather than:
MyModule.controller("DemoController", ['$http', function($http) {
$http.get("/contacts").success(function(response) {
contacts = response;
}]);
You are assigning response data to variable contacts which has no angular scope context
If you are using $scope as your data model for view it would be
$http.get("/contacts").then(function(response) {
$scope.contacts = response.data;
});
Or if using controllerAs alias in view:
var vm = this
$http.get("/contacts").then(function(response) {
vm.contacts = response.data;
});
Also need to inject $http in controller

Passing params to an angular service from a controller?

I'm an angular newby. I'm hoping to pass params to a service that fetches data form a server depending on those params.
for example, if I want to pass a book name string and then use it in the service to concatenate with the request url. The documentation does not show clearly in this subject and I could not find helpful examples in other resources.
Let say, this is the controller:
app.controller('BookController', ['$scope', '$routeParams', 'books', function($scope, $routeParams, books) {
// sending params to books service before a successful return
books.success(function(data) {
$scope.book = data[$routeParams.bookId];
});
and this is the service
app.factory('books', ['$http', function($http) {
// var url = 'http://...' + ParamFromController + '.json'
return $http.get(url)
.success(function(data) {
return data;
})
.error(function(err) {
return err;
});
}]);
So, how can I send params to 'books' service and then use it in the service?
Thanks a lot in advance.
You can declare your service as:
app.factory('books', ['$http', function($http) {
// var url = 'http://...' + ParamFromController + '.json'
return {
getVal: function(url,options){
return $http.get(url,options)
}
}
}]);
and use it in your controller and provide appropriate params to pass into 'books' service:
app.controller('BookController', ['$scope', '$routeParams', 'books', function($scope, $routeParams, books) {
// sending params to books service before a successful return
books.getVal('api/activity.json',{'name':'abc'}).success(function(data) {
$scope.book = data[$routeParams.bookId];
});
Also, dont use the .success() callback both in your service and controller function. The books service is returning a promise($http returns a promise implicitly) and you can handle that in controller.
Right now you are returning the promise / result of the $http as the service instance.
Services are not meant to work this way. You should return an object that holds several properties / methods that define your service:
app.factory('books', ['$http', function($http) {
var instance = {
getBook: function(bookId) {
return $http.get(...);
}
}
return instance;
}
In the controller you can then use the books service as follows:
books
.getBook($routeParams.bookId)
.then(function (result) { ... });
app.factory('books', ['$http', function($http) {
var booksService = {};
booksService.getBook = function(bookId){
{
return $http.get(url, bookId);
};
return booksService;
}]);
and in your controller
app.controller('BookController', ['$scope', '$routeParams', 'books', function($scope, $routeParams, books) {
books.getBook($routeParams.bookId).success(function(data) {
$scope.book = data;
});

AngularJS App: Load data from JSON once and use it in several controllers

I'm working on a mobile app using AngularJS as a framework, currently I have a structure similar to this:
app.config(['$routeProvider', function($routeProvider) {
$routeProvider
.when('/', {
templateUrl : 'pages/home.html',
controller : 'homeCtrl'
})
.when('/one', {
templateUrl : 'pages/one.html',
controller : 'oneCtrl'
})
.when('/two', {
templateUrl : 'pages/two.html',
controller : 'twoCtrl'
});
}]);
app.controller('homeCtrl', ['$scope', function($scope) {
}]);
app.controller('oneCtrl', ['$scope', function($scope) {
}]);
app.controller('twoCtrl', ['$scope', function($scope) {
}]);
And then I'm displaying the content with an ng-view:
<div class="ng-view></div>
Things are working well but I need to load data from a JSON file to populate all the content of the app. What I want is to make and an AJAX call only once and then pass the data through all my different controllers. In my first attempt, I thought to create a Service with an $http.get() inside of it and include that in every controller, but it does not work because it makes a different ajax request everytime I inject and use the service. Since I'm new using angular I'm wondering what is the best way or the more "angular way" to achieve this without messing it up.
Edit: I'm adding the code of the service, which is just a simple $http.get request:
app.service('Data', ['$http', function($http) {
this.get = function() {
$http.get('data.json')
.success(function(result) {
return result;
})
}
});
Initialize the promise once, and return a reference to it:
No need to initialize another promise. $http returns one.
Just tack a .then() call on your promise to modify the result
angular.module('app', [])
.service('service', function($http){
this.promise = null;
function makeRequest() {
return $http.get('http://jsonplaceholder.typicode.com/posts/1')
.then(function(resp){
return resp.data;
});
}
this.getPromise = function(update){
if (update || !this.promise) {
this.promise = makeRequest();
}
return this.promise;
}
})
Codepen example
Edit: you may consider using $http cache instead. It can achieve the same results. From the docs:
If multiple identical requests are made using the same cache, which is not yet populated, one request will be made to the server and remaining requests will return the same response.
Try this to get JSON Data from a GET Link:
(function (app) {
'use strict';
app.factory('myService', MyService);
MyService.$inject = ['$q', '$http'];
function MyService($q, $http) {
var data;
var service = {
getData: getData
};
return service;
//////////////////////////////////////
function getData(refresh) {
if (refresh || !data) {
return $http.get('your_source').then(function(data){
this.data = data;
return data;
})
}
else {
var deferrer = $q.defer();
deferrer.resolve(data);
return deferrer.promise;
}
}
}
}(angular.module('app')));
Now you can add this dependency in your controller file and use:
myService.getData().then(function(data){
//use data here
}, function(err){
//Handle error here
});

Sharing dynamic data between two controllers with service AngularJS

I have two angular services that need to share models (a list of messages and an individual message), which they get from a call to our API. The service is as follows:
angular.module('CmServices', ['ngResource'])
.factory('Messages', function ($resource, $routeParams, $rootScope) {
var data = {};
data.rest = $resource(url, {}, {
query: {method:'GET', params: params},
post: {method:'POST', params: params}
});
// Trying to set this through a call to the API (needs to get param from route)
$rootScope.$on('$routeChangeSuccess', function(event, current, previous) {
var messages = data.rest.query({m_gid: $routeParams.gid}, function () {
data.messages = messages;
});
});
return data;
});
and the controllers are:
function MessagesCtrl ($scope, $http, $location, $routeParams, Messages) {
$scope.messages = Messages.messages;
}
function MessageCtrl ($scope, $http, $location, $routeParams, Messages) {
$scope.messages = Messages.messages[0];
}
But neither of the controllers update when the data loads from the REST API (I've logged the data coming back, and it definately does).
Instead of assigning a new array to data.messages like this:
data.messages = messages
use angular.copy() instead, which will populate the same array:
angular.copy(messages, data.messages)
That way, the controllers will see the update.
The problem is that you are returning a different version of data to each controller. I would place messages in $rootScope. So
data.rest.query({m_gid: $routeParams.gid}, function () {
$rootScope.messages = messages;
});
Incidentally, what is the purpose of setting the return value of data.rest.query to var messages? That variable gets blown as soon as you leave the function.

Categories

Resources