I am still learning angularjs and I have problem with understanding difference between $scope
and model
object and this currently block me to organize (use some best practice) my app.
As I understand $scope
should be read only (watched some tutorials where I heard this).
So when I load app I should use service
to get some data from database and store it in model
.
UPDATE
Right now all data that I get from server are stored in controller $scope and I am trying to move it to services and make controller dumber.
I also check this article and I am trying to use second or third option but still can't find best way to implement it.
This is my service and controller:
function dataService($http) {
var service = {
getToDoList: getToDoList,
getToDoListByType: getToDoListByType,
getToDoById: getToDoById
};
return service;
function getToDoList() { }
function getToDoListByType() { }
function getToDoById() { }
}
function toDoController($location) {
var vm = this;
vm.todos = [];
vm.title = 'toDoController';
activate();
function activate() {
return getToDos().then(function () {
console.log("ToDos loaded");
});
}
function getToDos() {
return dataservice.getToDoList()
.then(function (data) {
vm.todos = data;
return vm.todos;
});
}
}
But in this implementation to do list is again in the controller.
Where should I store this list after I get it from server and from where it should be set (from controller or from service) so I can manipulate this list in a cached way (keep it local and update it occasionally)?
I am ing from C# world and there I always used entity objects (e.g. User, Product, Item etc.) populate those object in a loop and store it in a list. I can't find a way how should I use this approach in angular too and if yes should that be service with properties only?
I use one service to keep the list and one service to contain CRUD functions.
If I load data in $scope
from my model how to update that scope later if some other part of code change data in my model?
Change can e from another controller or be updated via SignalR for example.
Also as I heard when I update data on view as $scope
should be readonly I need to update service and again how and when to update $scope
then?
I am sorry if my question is too noob but I would be thankful if someone can help me to understand where to keep what in angular?
I am still learning angularjs and I have problem with understanding difference between $scope
and model
object and this currently block me to organize (use some best practice) my app.
As I understand $scope
should be read only (watched some tutorials where I heard this).
So when I load app I should use service
to get some data from database and store it in model
.
UPDATE
Right now all data that I get from server are stored in controller $scope and I am trying to move it to services and make controller dumber.
I also check this article and I am trying to use second or third option but still can't find best way to implement it.
This is my service and controller:
function dataService($http) {
var service = {
getToDoList: getToDoList,
getToDoListByType: getToDoListByType,
getToDoById: getToDoById
};
return service;
function getToDoList() { }
function getToDoListByType() { }
function getToDoById() { }
}
function toDoController($location) {
var vm = this;
vm.todos = [];
vm.title = 'toDoController';
activate();
function activate() {
return getToDos().then(function () {
console.log("ToDos loaded");
});
}
function getToDos() {
return dataservice.getToDoList()
.then(function (data) {
vm.todos = data;
return vm.todos;
});
}
}
But in this implementation to do list is again in the controller.
Where should I store this list after I get it from server and from where it should be set (from controller or from service) so I can manipulate this list in a cached way (keep it local and update it occasionally)?
I am ing from C# world and there I always used entity objects (e.g. User, Product, Item etc.) populate those object in a loop and store it in a list. I can't find a way how should I use this approach in angular too and if yes should that be service with properties only?
I use one service to keep the list and one service to contain CRUD functions.
If I load data in $scope
from my model how to update that scope later if some other part of code change data in my model?
Change can e from another controller or be updated via SignalR for example.
Also as I heard when I update data on view as $scope
should be readonly I need to update service and again how and when to update $scope
then?
I am sorry if my question is too noob but I would be thankful if someone can help me to understand where to keep what in angular?
- At some point the ToDo list has to be in the controller or you won't be able to bind to it. What you want to abstract away is the operations that reach out to the service, so that if the server implementation changes you just need to change the data service, and not the controller. It also helps for unit testing because you can make a mock data service to return fake data. I also do the same for prototyping before writing any server code. – nbering Commented May 3, 2016 at 13:30
-
In example from question I created a service that abstract server calls. I will give another example:
Service gets the list
>return list to controller $scope
>display it on view
=> but now on the view I manipulate that array in items by adding some properties to each item (grouping, coloring etc.) that I need to add in order to display those data. And let's say that I wan't to change all those properties again (run loop again) but I need original data that I got from server. But as I returned list to controller I don't have original array anymore. – 1110 Commented May 3, 2016 at 13:42 - And as I don't want to make server call again I don't know what is good practice - where to keep that model. – 1110 Commented May 3, 2016 at 13:42
- To keep your model there is : @C.C. answer. Module like angularCache to have some cache that handle expiration of data and so on. sessionStorage for recent browsers. All of those elements must be used at Service layer. – Walfrat Commented May 4, 2016 at 7:41
4 Answers
Reset to default 4 +200The model is used more often in a software architectural pattern named Model–view–controller (MVC). You can't understand how the model works without having a knowledge of the full pattern. In this pattern, the web application is broken into ponents with the purpose to separate responsibilities. I will direct you with an example of full TODO code to see the real use of MVC.
Model: Take/manipulate all the domain data (more often you take this from the server). Here you create a clear API that gives access to the data, that happen with services. In a service you get data from the server, you keep them inside and next you deliver some functions that give access and when someone needs these data he just use the injection to take access to the service. Think of this kind of service as something like a singleton class with data, get/set and other methods. A rule is: if you don't know where something is going, more likely is going to the service.(FULL CODE)
.factory('api', function ($resource) {
'use strict';
var store = {
//HERE IS THE API
todos: [],
api: $resource('/api/todos/:id', null,
{
update: { method:'PUT' }
}
),
clearCompleted: function ()[..]
delete: function (todo)[..]
get: function () [..]
insert: function (todo)[..]
put: function (todo)[..]
};
return store;
})
Controller: In the images above, you can see easy the controller only get and not give from user interaction. Controllers don't manipulate the Dom. The data here is going from view (user) to the controller by using the scope (or using this
inside the controller) and later manipulate the model using the functions we get by inject the service (model). Many times we make the controller act as a mediator, which break the rule of MVC, by querying the model and passing the result to the view, that is a different pattern name MVP. A rule is: Your controllers must always be as leaner as possible.(FULL CODE)
.controller('TodoCtrl', function TodoCtrl($scope, $routeParams, $filter, store) {
//store is the model, we make this in app.js
//is the result of a factory we make up,and we named "api"
var todos = $scope.todos = store.todos;
[..]
//in html we call removeTODO
//<button class="destroy" ng-click="removeTodo(todo)"></button>
//We use user interaction to manipulate the model!
$scope.removeTodo = function (todo) {
store.delete(todo);//we use the api we make
};
[..]
View: As you can see in the image, model updates the view, not the controller. How? With directives and filters. Be careful, the view have only the presentation of the data (data-binding). Don't contain plex logic. I want to be clear, in MVC the view should access the model directly. Directives and filters deliver this function. If you want to do a DOM manipulation you must use a directive (not a controller). Note: we put the dom manipulation inside the pile and link function of the directive, not in the controller.(FULL CODE1 FULL CODE2)
I have problem with understanding the difference between $scope and model object
Scope is just refer to model as we see up, but is not the model! Scope is used for user interaction too, controller depends on scope and controller depends on model.
so I can manipulate this list in a cached way (keep it local and update it occasionally)?
There are many ways to solve this. Regular we use observer pattern, but in angular there is another way to do this that is better in most of the times. Here an example:
angular
.module("testApp", [])
.service("myDataService", function(){
this.dataContainer = {
valA : "car",
valB : "bike"
}
})
.controller("testCtrl", [
"$scope",
"myDataService",
function($scope, myDataService){
$scope.data = function(){
//you get always the update data and never store tha data
//to the controller
return myDataService.dataContainer;
};
}]);
For more information check this, has some amazing answers.
The Problem: You have some remote data. You want all your controllers to have access to it. You don't want them each to get it on their own.
One way to do this in Angular: Use a service. Services are all singletons. This means that your app will only have one instance of the service and can be used to share data. I looked at the link you shared and the below is an example of the second suggestion, "Service is a Model and a Service".
function dataService($http) {
var todos= [];
this.getTodos = function() { return todos; };
this.getToDoList= function() {
// use $http to get remote data and assign it to todos
};
}
Now you can do TodoService.getData() anywhere you've injected it, say maybe your .run block, and from then on, TodoService.getTodos() will return the same data the service got previously.
Alternatively, you can use the service exclusively to get data and not to store (your link's 3rd suggestion). To do that, you would not store var todos
in the service, or have a this.getTodos
, you would only have the getData function (and other data get functions). Then from each controller, you would run TodoService.getData() to run the mon http get function.
Where should I store this list after I get it from server and from where it should be set (from controller or from service) so I can manipulate this list in a cached way (keep it local and update it occasionally)?
If you want to store and manipulate it in a cached way, you want to keep your data in the service. Your controllers will get the data from the service. There are a bunch of articles on using services to talk between controllers. They talk about using $broadcast
to send your own events so that an update to one controller will update other independent controllers.
In either case: you do want to bind the todos
list to $scope
in your controller. This will allow you to output its contents in your view and use Angular magic like 2-way binding. In your code:
function toDoController($scope, dataService) {
$scope.todos = [];
activate();
function activate() {
return getToDos().then(function () {
console.log("ToDos loaded");
});
};
function getToDos() {
return dataService.getToDoList()
.then(function (data) {
$scope.todos = data;
return $scope.todos;
});
};
}
Then in your view, you can just reference {{todos}}
.
Angular doesn't e with an opinionated way to store data.
Some projects that have addressed this and other related issues:
https://github./mgonto/restangular
https://github./adrianlee44/ng-backbone
https://github./paysavvy/immutable-angular
What I've done in the past is write up a models
and collections
module that stores data. These are just simple constructors.
angular
.module('app.models', [])
.factory('app.models.User', ['$resource', function($resource) {
function User(name) {
this.name = name;
}
User.prototype.sayName = function() {
console.log(this.name)
};
User.prototype.getInfo = function(params) {
$resource.get(params).then(res => {
this.info = res.data;
});
};
return User;
});
And then in your view model you hook up the view...to the model!
['app.models.User', function Controller(User) {
this.user = new User('bob');
}]
<div>
<button ng-click="vm.user.sayName()">say name</button>
</div>
I haven't read exactly the same tutorials as you have, but I generally refer to the Angular Style Guide originally published by John Papa with considerable feedback from the Angular munity.
If you're using SignalR to update your models in real-time, I think what you're looking for is the concept of Unidirectional Data Flow. I don't have a great resource to point you at for this, but I've seen some examples of SignalR and Angular that you might find just looking around for the basic idea.
Overall, the goal is to have updates from from the server, to your application. So if your controller updates a value, your data model isn't updated by the controller code. Your application sends a write to the server and the server sends the new value back to the AngularJS app.
Angular versions before 1.5 did not have a concept of one-way data binding, so if you're using ng-model 2-way binding is automatic, so you generally need to treat the value you're binding against as temporary and then sync state with a cached value or the server when a user is done editing data.
Your question is pretty broad, so if you'd like a more specific answer or How To, you might want to include some information about what type of application you're writing and sometimes the size of the application (number of controllers/features) will give an idea on what practices will serve you best. Some of the best practices for very large apps seem like anti-patterns for simple weekend project apps.
发布者:admin,转转请注明出处:http://www.yc00.com/questions/1744224767a4563951.html
评论列表(0条)