AngularJS Todo List - too much controller logic?
This is a funny question because


One of the most readable Angular submissions on CR
There is probably too much logic in the controller indeed


Some observations:


It seems the controller knows too much, it should not know that 5 is the maximum amount of items, or that 1 is the minimum amount of items to be kept
It seems silly to pass the list to list every single time to listEdit, it is not DRY.
I know alert in this case is used because it is a prototype, but still..


I would counter propose something where listEdit is aware of the list after you make a connection, listEdit also knows about limits and gives feedback ( in the form of a string ) whenever it does something to the list.

The controller this way is very small, and easy to understand:

//Controller methods
toDo.controller('main', ['$scope', 'listEdit', function($scope, listEdit) {

  $scope.list = [];
  listEdit.linkList( $scope.list ); //&lt;- Magic happens here

  $scope.addToList = function() {
    $scope.feedback = listEdit.add($scope.todo);
  };

  $scope.remove = function(index) {
    $scope.feedback =  listEdit.remove(index);
  };

}]);


listEdit is then a little bigger:

toDo.factory('listEdit', function() {
  var _list = [],
      maxLength = 5,
      minLength = 1;

  return {
    add: function(item) {
      if( _list.length &gt;= maxLength )
        return 'Too many list items';
      _list.push(item);
      return item + ' is added';
    },
    remove: function(index) {
      if( _list.length == minLength )
        return 'You can\'t delete this last item';                
      var item = _list.splice(index, 1)[0];
      return item + ' has been deleted';
    },
    count: function() {
        return internalList.length;
    },
    linkList: function(list){
      _list = list;
    }
  };
});


I consciously chose for immediate return with feedback in case of a problem, then the intended activity and then giving positive feedback. My evil twin whispered this hackish alternative:

    add: function(item) {
      return _list.length &gt;= maxLength ?
        'Too many list items' :
        _list.push(item), item + ' is added';
    }


Also, you will find me railing against people using underscore to indicate that it is private when it is not. In this case, _list is actually private, so that is fine.

In order to show the feedback you would need to add div:

&lt;!DOCTYPE html&gt;
&lt;html ng-app="toDo" &gt;
&lt;head&gt;
&lt;script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.14/angular.min.js"&gt;&lt;/script&gt;
  &lt;meta charset="utf-8"&gt;
  &lt;title&gt;JS Bin&lt;/title&gt;
&lt;/head&gt;
&lt;body ng-controller="main"&gt;
    &lt;div&gt;{{feedback}}&amp;nbsp;&lt;/div&gt;
    &lt;input type="text" ng-model="todo"&gt;
    &lt;button ng-click="addToList()"&gt;Add to List&lt;/button&gt;
    &lt;div ng-repeat="todo in list track by $index"&gt;
    &lt;span ng-click="remove($index)"&gt;{{todo}}&lt;/span&gt;
    &lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;


I used the &amp;nbsp; trick to make sure the elements dont reflow after the first element is added, probably not best practice, HTML is not my forte.

In the end, it was fun to play with this in jsbin: http://jsbin.com/vesomu/2/edit

Also, check this : a simple todo app by Angular pro's.