Where I should keep data using AngularJS? - javascript

I've got a question about storing data in AngularJS. Should I use some kind of service, or controller to keep data? I saw different codes in Angular and one time people store data in service, other, in controller. I would say that the proper way is to keep it inside factory, but is it a good practice?
Thanks!

Well, it depends on what you mean "storing data" for you...
If you mean keeping data in some place just for passing it between controllers, then this place is a service.
If you mean keeping data so it can persist even after a page refresh or after closing the browser and reopening the same app then you can use the javascript apis for sessionStorage and localStorage (take into account that older browsers may not have these apis and you would have to polyfill them). I've used an angular service for this that have given good results: https://github.com/tymondesigns/angular-locker.
If you mean persist the data for using it among other systems different than yours, the you should rely on a database server, either yours or from a third party (take a look at Firebird).
Of course you have more options, but they don't differ from the ones you have if you use plain javascript. Each of them could be treated in an "Angular way" if you create a service to manage them (IndexedDB, WebSQL, etc.) In the end it depends on what you're trying to achive.

If you need to use the data across multiple views / controllers, for example a logged in user, then i would recommend a service which holds the data for you. This way you can access it from anywhere you inject it. However, if you need your data only in one of your controllers, i dont see a reason to create a service, just store it in the controller.

Related

How to avoid global variables when different functions need data from database call. (JS)

I'll try to explain the title (-;
I'm making an app. It calls a database in the backend.
The app also collects user information on different screens. They need to be combined with the data from the backend in different ways and give an output to the user.
I want to call the db once and not from every function. So now, on the 'init' I define a lot of global variables.
I know* that all this global variable stuff is no a good idea. But what is?
*)have read
This is where a JavaScript library may serve you well. Frameworks such as React allow you to set up ways of handling different models such as the user model you describe and making it easier to work with each model throughout the app
Thanks #finalfreq' i see there are a lot of frameworks. And also, it will take a while to learn and work with them. But i'm glad i don't have to search anymore within Javascript itself. (-;

Passing $scope to angularJs service/factory a bad idea?

I am working on a project where in there are almost 90+ modules.
All modules has a set of input fields and on submit the data should be saved on the server.
At any given point in time only one module is active. But there can be open modules in the background.
Submit button is common to all modules, meaning there is only one Submit button throughout the application.
Below picture explains it more.
The prime motto is to keep the individual module changes to minimum and a way to handle certain things(validation, reload etc) in the module from a central place.
The current approach I am planning is,
Use a 'moduleInit' directive that all module should include in its
partial.
The directive takes the $scope of the module and pass it to a
common service/factory (pushConfigService)
The pushConfigService stores and keep this scope as long as the
module is open. Once the scope is destroyed the reference of the
same will be removed from the pushConfigService.
The footer panel is another directive with Submit button in it and
calls a save function in the pushConfigService which in turn calls
a $scope function in the module to get the form data.
pushConfigService talks to a bunch of other services like
dirtyChecker, apiGenerator and finally post data to the server.
Each module will have a set of scope methods defined with some standard names. Eg: _submit, _onSubmit, _cancel, _reload etc.
Another way to handle this, broadcast the submit event and each module listens to the same. There is possibility more actions will be added to the footer panel.
So I am little bit hesitant to use the broadcast approach.
My question, Is it a good idea to pass controller scope to a service? Any alternate suggestions?
Thanks in advance.
I believe your core concept is a nice way to handle this setup. Yet I'd suggest to split business logic from UI. I don't have a sample of your code so it is a little hard to build an exact example. Yet since you're using the $scope variable I'm going to assume you're not using a styleguide like or similar to John Papa's. His ways encourage you to not use the $scope and to stay close to actual JavaScript "classes".
How does this make a difference?
Instead of passing the whole scope, you'd be able to just pass the instance of your specific module. For one it is less confusing to you and colleagues to have a concrete interface to operate on instead of having to figure out the composition of given scope. In addition it prevents services from being able to alter the $scope.
The latter could be considered a good practice. Having just the controllers alter the scope make it easy to find the code which alters and manages the UI. From there on the controller could access services to do the actual logic.
Taking it one step further
So passing the class instance instead of scope should be an easy adjustment to the already proposed setup. But please consider the following setup as well.
It seems there are quite some different ways to handle and process the data provided by the module/end user. This logic is now implemented in the controller. One might think some of these modules share similar handling methods (big assumption there). You could move this logic to, so to speak, saving strategies, in services. On activation of a module, this module will set its preferred saving strategy in the service which handles the submit button click. Or more precisely, the save data method which should be called from the onClick handler in the controller.
Now these services/strategies might be shared among controllers, potentially setting up for a better workflow and less duplicated code.

Angular.js Method duplication in controller when using service

I've created a BookService that is used for storing (add), getting (getAll) and removing (remove) books. Now I want to use this BookService inside my controller to publish some methods that I can later use in my view. My controller looks like the following:
app.controller('BookController', ['BookService', '$scope', function(BookService, $scope) {
$scope.addBook = function() { BookService.add(); }
$scope.getAllBooks = function() { BookService.getAll(); }
$scope.removeBook = function() { BookService.remove(); }
}]);
As you can see, the controller is just a proxy that forwards the method calls to the service. Is this in general bad practice? And is there a better way to solve that using Angular.js? Calling the service directly from the view without a controller seems, to me like a bigger problem.
Best Practice
From what I can see this is perfectly good practice, I'm assuming that you're using $scope here to bind these services to a button or something similar. The Idea of using a factory or a service is to create some well organised reusable code that you can then instantiate in your controller exactly like you have done.
Controllers can get quite complex so moving basic functionality to your service is the best thing to do. In your case you have a relatively simple controller so you may not see the benefit of coding in this way. But I assure you that as your code base grows you will be required to code like this just to keep things readable.
Note
Just as an extra note I've added a data process that you might take with an example of a database request
database > API > service/factory > controller > view
This would be the correct path to take when requesting something from a database.
What you have shown is not bad practice; it is in fact recommended that you abstract resource management logic (like adding, removing and finding resources of the same type) into a separate service, for organization and maintainability and reusability purposes.
I do understand from your example how the controller seems to be just a proxy to the service though, and why you would think it's repetitive and possibly redundant. Let me expand on your example to see if I can explain the reasons for abstracting the logic. In doing so, let's consider only the adding operation, even though the logic would apply to others as well.
Reason 1: adding a book (or any resource for that matter) in a web app is usually more complicated than just a bookService.add() call. It requires having some sort of form to enter the details, a submit button to handle the actual request, possible massaging of the entered data, adding new fields like time stamps and author ids, and persisting to some data storage. The first two or three of those steps would be applicable to the screen or view from which you are adding, so it makes sense to put that in a controller (the view model), whereas the rest of the steps should go into the generic service.
Now say you have another screen where you see a friend's list of books and you can add it to your list by selecting a book. In that case, the controller logic for that view's controller will differ from the previous example, but the service steps will still be identical, and thus do not need to be duplicated since the service can be injected into both controllers.
That's a big win.
Example 2: let's say you've already split the code between controller and service as describe in example 1 above. Then you decide that your data storage needs have changed and now you want to update your logic to save to a different database system. Now instead of having to change all the controllers, you just change your services and the everything works.
This is also a really big win.
Yes you'ved done this correctly. Just keep in mind that as you scaled up your app in complexity, you'll want to have isolated scopes, (and) decomposition into component directives. Each directive will have its own controller and template fragment.

Using Angular, where should I store my constants?

This question has less to do with how to do something, but more about best practices and what do others do?
I have a few services where I am using some kind of an external API (in this case the session storage api in the browser), where I am reusing the same constant string, the name of the company and the application, let's call it "ACME.Storage.", and this I want to prepend at the start of every "key" string. I see my options as:
I can just reuse the string "ACME.Storage." in every call.
I can create a JavaScript function where I create a new storage object that is configured with "ACME.Storage." once. That way, "ACME.Storage." appears once in my code.
I can create a local variable ans store "ACME.Storage." in it, then reuse that. Again, the string literal appears only once in my code.
I can create a separate javascript object that I can share.
I can use an AngularJS "constant"
I can add as a field to the app of config file.
I can store it somewhere where localized literal strings (even though this particular string isn't localized) and get it through a translation service.
I'm leaning toward using the "constant" service 'cause it's the one that's easily injectable. My only concern is that it's less encapsulated than some of the other options.
Opinions on the best practice?
To expand upon what Whishler posted, you can (and probably should) use the Constant module that Angular provides. Complete docs are found here: http://docs.angularjs.org/api/ng/type/angular.Module. Services are a common place for constants, but the Constant modules get applied before other provide methods. Another option would be Value, but it does pretty much the same thing.
Generally, I put constants into a service.
Depending what I'm doing, I may create a service that does nothing but store related constants. Or I may add them to another service representing a 'model'.
I'll also add that JavaScript doesn't officially have constants; so unless you wrote some code--such as your own accessors--you're just dealing with a variable that could be changed during the execution.

Isn't it dangerous to have query information in javascript using breezejs?

Just starting to play with breeze.js because of the obvious gains in coding time, i.e. managing to access model data from the server direct within Javascript (I am a newbie here, so obviously bare with!).
In the past I have used the stock ajax calls to get/post data to the server, and I have used a few different client tools in the past to provide some help in querying local data, such as jLinq.
My question is this. Isn't it dangerous to have essentially full model query access in Javascript? I must be missing something because it looks like a really well thought through tool. In the past I have at least controlled what can be sent to the client via the backend query process, and again using something like jLinq etc I could filter the data etc. I can also understand the trade-off perhaps with gaining the direct query/none-duplicating local model problem, so just if anyone could provide some insight to this?
Thanks!
EDIT
Obviously I am not the only one, however I am guessing there is a reasonable response - maybe limiting the data being requested using DTO methods or something? The other question posted is here
It can be dangerous to expose the full business model. It can be dangerous to allow unrestrained querying of even that part of the model that you want to expose to the client. This is true whether you offer an easy-to-query API or one that is difficult to query.
That's why our teams are careful about how we construct our services.
You should only expose types that your client app needs. If you want to limit access to authorized instances of a type, you can write carefully prescribed non-queryable service methods. Breeze can call them just fine. You don't have to use the Breeze query facilities for every request. You'll still benefit from the caching, related-entity-navigation, change-tracking, validation, save-bundling, cache-querying, offline support.
Repeat: your service methods don't have to return IQueryable. Even when they do return IQueryable, you can easily write the service method to constrain the query results to just those entities the user is authorized to see.
Fortunately, you can blend the two approaches in the same service or in collaborating services.
Breeze gives you choices. It's up to you to exercise those choices wisely. Go out there and design your services to fit your requirements.
Breeze isn't meant to be your business logic in that sense. Keeping in mind the rule of thumb that if you do something in Javascript, anyone can do it, you ought to be restricting the visibility of your own service data as needed.
In other words, it's useful for you if you meant to make the data publicly visible anyway. But only expose the entities that you're happy exposing and allowing anyone to query; another way to look at it is that your API becomes a public API for your website (but not one you advertise and tell everyone to use).
I am personally not a fan of doing things this way as there is a dependency created on the schema of the backend implementation. If I want to make changes to my database tables, I now have to take my Javascript into consideration. I also lack in terms of integration and unit testing.
However, it can have its uses if you want to quickly build a website feature on non-sensitive data without having to build the service methods and various layers of implementation of it.
What about when you expose the Metadata? Isn't that considered dangerous. IMHO is not safe to expose metadata from the DbContext. I know you can construct metadata on the client, but the point is to do things as quickly as possible(if safe).

Categories

Resources