Angular 1.x : Specific Scenario When To Use Controller / Service - angularjs

Let's say, In a web app, a particular JSON is frequently used across multiple pages, for e.g:
{
"employees":[
{"firstName":"John", "lastName":"Doe"},
{"firstName":"Anna", "lastName":"Smith"},
{"firstName":"Peter", "lastName":"Jones"}
]
}
So getting a firstName() or lastName() for all employees should be considered as a part of the controller or the Service?
I could only think of using services as it is frequently used across app and controller be getting this data and it will be thinner too.
Is this right approach ?

You have following options:
Make a REST/HTTP call every time you need this data in a certain controller. Therefore, create a EmployeesService which calls the HTTP
endpoint to get the data.
Call the data once, and store it in a service. Afterwards, inject the service everywhere you need the data.
Fetch the data from the HTTP endpoint when your app starts, and store it in the local storage of the browser or inside the $rootScope,
so you can access it from everywhere.
In the end, it depends on:
How big is your app/how much data you have to share?
How often gets this data updated?
Which Views do need access to this data?
So yes, with a service, you are on a safe side. Afterwards, inject it into the controller and use it from there. How and how often the data gets into the service: Your decision.

Related

What is the Best way to manage state in AngularJS

I am a ASP.Net developer and trying to learn AngularJS. There are several ways to manage state in asp.net such as Session, ViewState, Cookies etc.
Can someone explain me or direct me to a good example which is showing state management best practices in angularJs.
For example once user log in to the application I want to store the current user object in client side.
There are many ways to maintain states. You can maintain a state, either using "$scope", or "$rootScope" in AngularJS.
For example :-
angular.module('SampleApp')
.controller('ExampleCtrl', ['$scope', '$rootScope', ExampleCtrl])
function ExampleCtrl($scope, $rootScope) {
// for set data
$scope.data="Hello";
$rootScope.Globaldata="Hello World";
}
In above example, "$scope" is used for page level or local variable and "$rootScope" is used for maintaining the state globally.
You can access the value of "$rootScope" anywhere in your application, whereas you don't use the value of "$scope".
Another way to store or to maintain data, is using LocalStorage:-
You can store your value using "angular-local-storage" and "ngCookies".
Follow Below Link :-
https://docs.angularjs.org/api/ngCookies/service/$cookies
You can use angular-local-storage, ngCookies to save states and provide persistence. Additionally you can use IndexedDB storage in newer browsers to provide persistence, with the condition that its not available in all the browsers.
A better strategy is to use combination of IndexedDB, localStorage, ngCookies with a fallback to in-memory storage. In order to do this you need to have a consistent api/ service which provides this functionality and handles the fallback gracefully within the service itself so that the consumer of the service doesn't need to bother about the fallback mechanism
Checkout this library https://www.npmjs.com/package/angularjs-store
This can help you manage your application state much simpler as it will force you to have a one way data flow on your application.
Ng-Cookies
You could add the Angular service ng-cookies this lets you store and retrieve cookies when you inject it into you module. Here is a link to the docs.
Add new service
To add a new service to you angular app you will first need to download the js files and add them too you index.html like (from CDN)
<script type="text/javascript" src=""//ajax.googleapis.com/ajax/libs/angularjs/X.Y.Z/angular-cookies.js""></script>
Load into app
In any module you want to use ng-cookies inject like this
angular.module('app', ['ngCookies']);
Conclusion
Your app now has access to the read and write cookie methods that come with ng-cookies But remember that the CookieStore service is depreciated so only use ng-cookie
from Angular Docs
Note: The $cookieStore service is deprecated. Please use the $cookies service instead.
Beyond this the Docs are pretty good. Best of luck.
There are a lot of ways in which this could be done. I use sample codes based on https://github.com/alarv/ng-login in my applications. I'm using tokens to authenticate the requests.
The sample code demonstrates
saving user information in a service called "Session".
2.statechangeEvents to handle authentication with roles.
interceptors to handle authentication/ authorization errors in http
requests.
If you are securing the html resources also, you might need to redirect the page to login page from the server side.
That highly depends on what kind of authentication mechanism you are using on back end.I use token based and session less systems for my projects so I use browsers local storage for storage of authentication tokens but if you are using sessions you will need to use cookies.
If you use local storage make sure you use JSON.stringify() first when saving and on retrieval of that Object make sure you use JSON.parse()
Disadvantage of localstorage : only html5 supported
So if your website needs to give support to older browsers you will need to have a fallback on cookies.

angularJS - webapp architecture

I have to build an angularJS webapp and found many resource for best practice but there are still some questions that were not answered. I hope you can help me.
Question 1: Model
One thing is, where should i store my model and handle changes to it?
I found some different solutions but they were all for simple datastructures. I have something like User ---> Subscription ---> Device ---> HardwareReport. And this is just one branch of the datastructure tree.
My question is where should i store it so that every Controller can access the data.
Current solution:
Current solution would be, not to store the data structure but to have a service for every object type like UserService or SubscriptionService.
And every of these services handles the communication with the backend server and keeps the return value in a cache.
Downside:
If a controller needs for example all devices of the user it has to deal with all services and can't just go through the data-structure tree. What if one controller changes for example the device object of the user. How should i notify other controllers?
Question 2: lazy configure/instantiate services
Here is a part of the application.
I have an AppController, LoginController and a MapController.
And i have a BackendService which encapsulates the API-Calls and is used by UserService and SubscriptionService.
When i login into my webapp the LoginController uses the SessionService to verify the login data and receives an accessToken for the API.
This accessToken must be set in the BackendService to be added to the header.
But the BackendService is already injected in other services.
Current solution:
Just set the AccessToken from LoginController like
BackendService.setAuth(accessToken);
Because the service is singleton all other services that uses BackendService will be have the correct setup BackendService.
Downside:
I can call functions of the BackendService before setting the access token and this would result in errors.
** Alternative solution: **
I just implement a BackendServiceFactory which i can use at any time to create a new BackendService instance. So i can create the BackendService in the LoginController after login.
Downside: I have to pass this object through all my services and controller because it won't be injected by DI.
Quite long questions but i hope you can give me some suggestions how to build this app.

How to receive postback using Express and Angular?

I have a server written in Express that interfaces with an application written in Angular on the client.
My Express server is receiving a post from a third-party service to a route which will perform business logic, and then here is where I am a little uncertain about the best path forward.
After receiving the post variables, I want to redirect the request to an Angular route, but I want to make those received post variables available to the route as well.
Somehow, I want to be able to mix the res.json() and res.redirect() method, but I'm pretty sure they both end the response.
What would be a logical way to structure this?
Update: To expand on the issue, imagine I have a route called /receivetransaction which receives some postback variables, including transaction ID, amount etc. I want to perform business logic (save to a database), and then redirect the user to /thankyou (an angular route) but have them be able to access that data that was just received in the postback.
It looks like maybe my best option would be to save to the database, and then send the transaction-id as JSON to the angular view, which will then hit the database and pull the info. A little inefficient though (not really a big deal) but I would hope there would be another way around it.
What I've decided to do is the following:
After the express route receives the postback variables, it performs the business logic (specifically saving the data to the database), and redirects the request to the angular route with a query var indicating the id of the transaction.
The angular controller uses $location.search() to pull the transaction id from the query var, and from there it performs a get request to the express API, which performs authentication and loads the relevant information into $scope variables to be passed to the view.

Storing data in factories or services?

https://github.com/johnpapa/angular-styleguide#style-y060
Shows a single responsibility factory making $http requests and handling some logic and errors, returning the promise. Typically from there, I would store the results in a service (as opposed to controller $scope so I can access it anywhere, including in directives). However:
Conversely, don't create a service whose only purpose in life is to
store and return bits of data.
https://docs.angularjs.org/misc/faq
Should I store the data on the factory itself? Or continue with factory -> http / service -> storage?
I'm not asking what the code difference is between the two, "one can be new'd etc", I'm asking for those that follow Angular best practices (skinny controllers, etc) what are the rules concerning the roles of a factory after it's fetched the data?
Should I store the data on the factory itself? Or continue with
factory -> http / service -> storage?
I see nothing wrong here. And don't forget, there are constant and value that fit nicely to 'store and return bits of data'. And caching solutions (i.e. $cacheFactory, angular-cache) that can help you to improve app design.
You can't blame Angular FAQ for advocating $rootScope, but keep in mind that it could be an obsolete opinion of some team member. Things have changed in Angular, and opinions have also changed in Angular community. You shouldn't trust a single developer on how exactly you should write your code (even if Papa is the surname), but it surely wasn't he who introduced the questionable concept of 'scope' into JS framework that was later anathematized even by its creator.

How do I organize/structure AngularJS logic

Im unsure how I should structure an AngularJS app logicwise. On the serverside I do it like this:
Request is handled by controllers
Controllers call a service with the incoming data
Services do database queries by calling the appropriate methods on the database layers
So on the client side I have the controllers that bind the scope to my logic, my JSON data objects and my Services.
Do I put everything that is not related to the scope into a seperate service?
Where do I put my data objects? Into a seperate service?
What about two way databinding? Doesnt that write back to my JSON data objects even if I dont want that?
How do I organize my run method? Do I group everything by resource and put it into ArticlesService.init() for instance?
Should my services keep the JSON data objects and do all the updating on the local and remote collection (as in delete a JSON object and then call a DELETE method on the remote server?)

Resources