Suppose I have a REST service that returns JSON describing a person. Here's
how I would handle that.

1) Create an Angular service that calls the REST service or add a method to
an existing Angular service that does that. The service method would return
the result of a call to $http.get which is a promise. That method would
look something like this:

  svc.get = function (firstName, lastName) {
    var url = restUrlPrefix + '/person?firstName=' + firstName +
'&lastName=' + lastName;
    return $http.get(url);
  };

2) In the controller, add a method on the scope that is perhaps called when
the user clicks a button (using ng-click). That method would look something
like this:

$scope.getPerson = function () {
  personSvc.get($scope.firstName, $scope.lastName).then(
    function (res) {
      $scope.person = res.data;
    },
    handleError);

The key points for me are:
1) The controller doesn't make REST calls. The service does that.
2) The service doesn't access or modify $scope properties. The controller
does that.


On Tue, Aug 12, 2014 at 1:53 PM, Colin Kahn <[email protected]> wrote:

>  If anything needs to be assigned to a scope property, service methods
>> should return it to controller functions and those should modify the scope.
>
>
> Would that be similar to the example above for method 2 where the getCount
> method on the controller returns serviceCounter.count? Or is there a
> different way of doing that?
>
>
> On Monday, August 11, 2014 7:29:18 PM UTC-7, Mark Volkmann wrote:
>
>> In my opinion, only controllers should modify the scope. For that reason,
>> only method 2 makes sense. Controllers should call service methods to run
>> business logic and make REST calls. If anything needs to be assigned to a
>> scope property, service methods should return it to controller functions
>> and those should modify the scope.
>>
>> ---
>> R. Mark Volkmann
>> Object Computing, Inc.
>>
>> On Aug 11, 2014, at 8:57 PM, Colin Kahn <[email protected]> wrote:
>>
>> There's quite a bit out there about using controllers and services
>> together, and was hoping to start a discussion to try and nail down some
>> best practices.
>>
>> There's three different methods i've seen for using controllers and
>> services together. They all assume (I believe) that you're holding the
>> state in your services, and your controllers are stateless.
>>
>> Method 1: Expose Service to Template
>>
>> This one is probably the simplest. You treat your service like a model
>> and you put it on scope (or on your controller and your controller on scope
>> using the "as" syntax) and then in your templates access its properties and
>> methods.
>>
>> app.service('serviceCounter', function() {
>>   this.count = 0;
>>   this.increment = function () {
>>     this.count++;
>>   };
>> })
>> .controller('ServiceCounterController', function (serviceCounter) {
>>   this.serviceCounter = serviceCounter
>> });
>>
>> <div ng-controller="ServiceCounterController as serviceCounterCtrl">
>>   {{serviceCounterCtrl.serviceCounter.count}}
>>   <button ng-click="serviceCounterCtrl.serviceCounter.increment()">Add
>> One</button>
>> </div>
>>
>> Method 2: Wrap Methods in Controller
>>
>> For this, you create a specific API in your controller that uses methods
>> from your service:
>>
>> app.service('serviceCounter', function() {
>>   this.count = 0;
>>   this.increment = function () {
>>     this.count++;
>>   };
>> })
>> .controller('ServiceCounterController', function (serviceCounter) {
>>   this.getCount = function () {
>>     return serviceCounter.count;
>>   };
>>   this.addOne = function () {
>>     serviceCounter.increment();
>>   };
>> });
>>
>> <div ng-controller="ServiceCounterController as serviceCounterCtrl">
>>   {{serviceCounterCtrl.getCount()}}
>>   <button ng-click="serviceCounterCtrl.addOne()">Add One</button>
>> </div>
>>
>> Method 3: Reassign Service Methods to Controller
>>
>> Here, you would reassign your methods onto the controller:
>>
>> app.service('serviceCounter', function() {
>>   var count = 0;
>>   this.increment = function () {
>>     count++;
>>   };
>>   this.getCount = function () {
>>     return count;
>>   };
>> })
>> .controller('ServiceCounterController', function (serviceCounter) {
>>   this.getCount = serviceCounter.getCount;
>>   this.addOne = serviceCounter.increment;
>> });
>>
>> <div ng-controller="ServiceCounterController as serviceCounterCtrl">
>>   {{serviceCounterCtrl.getCount()}}
>>   <button ng-click="serviceCounterCtrl.addOne()">Add One</button>
>> </div>
>>
>> Obviously if someone has better examples of any of these please share.
>>
>> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
>>
>> My pros and cons list is as follows:
>>
>> *Method 1: Expose Service to Template*
>>
>> *Pro:*
>>
>> - Simple, very obvious where you're accessing the properties and methods
>> - Able to bind to the services properties without needing a $watch in
>> your controller or using events
>>
>> *Cons:*
>>
>> - Verbose, your template expressions become very long due to the
>> repetition of the name
>> - Service is coupled with templates, changes to how the service works
>> could break your UI
>>
>>
>> *Method 2: Wrap Methods in Controller*
>>
>> *Pro:*
>>
>> - Still obvious where methods and properties come from (everything goes
>> through the controller)
>> - Service is not coupled with the templates, if the service changes your
>> controller methods can be updated without touching the templates
>>
>> *Cons:*
>>
>> - Verbose, everything needs to be wrapped
>> - Properties must be accessed through methods, increasing function calls
>> during each watch cycle
>>
>> * Method 3: Reassign Service Methods to Controller*
>>
>> *Pros:*
>>
>> - Less verbose than method 2, while keeping some separation between the
>> service and the template
>> - Service acts more like a module with private state
>>
>> *Cons:*
>>
>> - Could be unclear how things are being updated since `this` is actually
>> the `this` of the controller
>> - Still can't bind directly to properties, state must be wrapped in
>> functions
>>
>> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -
>>
>> If you've got any insight, or have tried these methods to success please
>> post. Also, if I've left any ways of doing this out I can update this post.
>>
>>
>>  --
>> You received this message because you are subscribed to the Google Groups
>> "AngularJS" group.
>> To unsubscribe from this group and stop receiving emails from it, send an
>> email to [email protected].
>> To post to this group, send email to [email protected].
>>
>> Visit this group at http://groups.google.com/group/angular.
>> For more options, visit https://groups.google.com/d/optout.
>>
>>  --
> You received this message because you are subscribed to the Google Groups
> "AngularJS" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to [email protected].
> To post to this group, send email to [email protected].
> Visit this group at http://groups.google.com/group/angular.
> For more options, visit https://groups.google.com/d/optout.
>



-- 
R. Mark Volkmann
Object Computing, Inc.

-- 
You received this message because you are subscribed to the Google Groups 
"AngularJS" group.
To unsubscribe from this group and stop receiving emails from it, send an email 
to [email protected].
To post to this group, send email to [email protected].
Visit this group at http://groups.google.com/group/angular.
For more options, visit https://groups.google.com/d/optout.

Reply via email to