After reading these articles I've been trying to decouple my app:
http://toddmotto.com/opinionated-angular-js-styleguide-for-teams/
http://toddmotto.com/rethinking-angular-js-controllers/
One of the insight of the articles is this one:
Controller drives Model changes, and View changes. Keyword; drives,
not creates/persists, it triggers them!
I've found easy to manage persistent data in my services but I still need to create data in the controllers to handle view state changes or transforming data from the services.
Is there a pattern to avoid creating ANY data in the controller while being able to manage the view?
Related
I create a project structure of a web-app with angular.
I create my directories with services, controllers and views.
Then, my team ask me: where are the models? (Nobody of us have worked with angular)
And I answered that in the service, because is where the data persist.
But Im no really sure, and I cant find useful info about this.
What you are looking for is a factory provider. You can create a factory with a collection inside, and this "class" has operations to handle the collection and sincronize it with the back-end.
See this example:
https://github.com/AngularClass/angular-websocket/blob/master/README.md
You can see how to create a collection and initialize it with data that comes from a websocket.
Aditionally you can create operations to handle the collection
This could be consider a "model" in angular.
It is a best practice to keep business logic in Services (and not in controllers, for example). This is, among other reasons, because controllers are instantiated for each view and Services are singeltons.
You can refer to those great posts for more details:
https://johnpapa.net/sharing-data-in-an-angular-controller-or-an-angular-service/
http://teropa.info/blog/2014/10/24/how-ive-improved-my-angular-apps-by-banning-ng-controller.html
https://toddmotto.com/rethinking-angular-js-controllers/
I'm going to assume from the verbiage you've used that you're referring to Angular 1.x.
Services are typically used by controllers to pull data from a provider not displayed in the view. The provider can be a public api, a static file on your own server, a mongo database, etc.
A model for a controller represents the data being manipulated between the view and the controller (refer to ngModel).
Is there a way to maintain $scope when changing views and coming back?
When i load a certain view there is some heavy loading (loading data), but if i switch views and comeback to this one al the data is reloading again. Is there a way to prevent this?
I am not looking to share data between views, I just wish to have the old state when I return to the same view.
There's a few ways to handle this.
$rootScope
You might be able to store the values in the $rootScope, I don't believe it changes when you use the internal routing module, but I would not recommend this.
Services (My Immediate recommendation)
You can use a static service, where the data can be stored, either constantly, or while changing route. Then you can load the data into the $scope again.
Caching
AngularJS has an inbuilt cache, you can use. This is great if you only need to store some of it, or for a smaller amount of time. Read the documentation for the CacheFactory here.
WebSQL or localstorage
For large amounts of data, you want to store between sessions, you can use the WebSQL database in most browsers, or store it as text in the localStorage in the browser.
So my understanding is that factories are singletons so any stateful data for a session would be ill placed here.
My next point of call was a service which returns a new instance of the service when injected however I am unsure how I would share one instance of the service to multiple controllers.
Is this an accepted way to solve this issue or does angular provide a better way?
My current use case is that I have a view with some partial views (each partial has it's own controller) and a modal window which takes in a row id and will display data dependant on that data.
I need to be able to share a instance of the service (or equivalent) across these controllers but on a per session basis.
How is this best done?
The singleton exists for one user and loaded SPA. Thats what you would usually refer to as a session. Its a good place to store data that needs to be accessed by different controllers.
I don't really understand what a model is in AngularJS. I know what a model is in the context of an MVC framework. For example in PHP I would create a model, like ApiModel.php or something like that, and in there I would put all sorts of cool stuff for the controller to work with.
This doesn't seem to be the way AngularJS thinks of models, in fact I can't find any good explanation of how to implement a model in AngularJS, but everywhere talks about them.
What is a model in AngularJS and how do I use them in the traditional MVC way?
A model in AngularJS specifically communicates with its associated views and controllers and notifies it whether there is a change in its state.
A more thorough description of what is a model can be found in the following link:
https://web.archive.org/web/20140502052028/http://www.webdeveasy.com/angularjs-data-model/
This article is relevant to your inquiry.
More specifically, he mentions that
Model classes encapsulate your application’s data and provide an API to access and manipulate that data. The other classes in your application will make requests of models via this API. When data on the model is updated, the model dispatches events that the other classes within your application can react to. Models are appropriate for capturing the domain logic, such as performing calculations or other manipulations.
A model is just the data that your application consumes.
If the data needs to be dynamic (i.e subject to CRUD operations) you would get this data from a remote source like a database (or even a flat-file) using angularjs' $http in a service or factory and then pass it to the Controller.
If you have a small app for read-only data, then you can hard-code it directly into a Controller.
The most popular data format for angularjs applications these days is JSON because of its flexibility.
The view (or front-end) would then access this data that lives on the scope in the Controller using ng-bind or ng-model or interpolation {{...}}
I'm new to AngularJS and having a hard time wrapping my head around the conceptual model.
Let's say I want to have an object hierarchy to model a stash repository: Projects contain Repositories contain Tags. Do I create one app, one module and multiple controllers? (Can a module have multiple controllers?) Separate app per object type? Separate module per object type?
All the various data types will be populated by making REST API queries. Read-only for now. Does that change things?
Also, why are they called controllers? They seem to be models. As far as I can tell the controller is actually the AngularJS plumbing.
Here is my rather simple explanation:
A module is just simply a container for all the bits and pieces of your app (services, controllers, directives, filters etc).
Your application may contain different modules - some that you wrote and other third party ones, such as ngGrid for example.
You define a module like this:
var myAppModule = angular.module('myApp', []);
A controller is where the business logic of your application resides. The controller may handle the model, but it is not the model.
The AngularJS documentation for controllers states:
Use controllers to:
Set up the initial state of the $scope object. Add behavior to the
$scope object.
I break up my controllers in to the logical functions that they are supposed to handle. For example, I've written an app to help with combat tracking in a tabletop RPG. I have a controller that handles martial combat and another that handles magick. I also have another controller that helps with the characters. All these controllers are part of my combat app.
I only have one service that is responsible for querying a REST API to retrieve stats and results from a database.
The AngularJS documentation has improved a lot recently and I would recommend reading through it to give you a rough idea of how things work together!
In your example, I'd have a separate controller for each of Projects, Repositories and Tags. I'd have a service to query your datatypes. These would be grouped as part of one module/app.