Empty array inside controller function called by directive - AngularJS
I have a rather complicated problem that seems trivial, but I can't find a good way to solve it.
Essentially I am creating a to-do list app using Angular and Angular-Material .
I have main.html where the important part is:
<md-content ng-show="mainCtrl.todos.length">
<md-list class="todo_list" flex>
<md-subheader class="md-no-sticky">{{mainCtrl.todoList.label}}</md-subheader>
<acme-todo ng-show="mainCtrl.todos" ng-repeat="todo in mainCtrl.todos track by $index"
text="todo.content" index="$index"></acme-todo>
</md-list>
</md-content>
Where acme-todo
is the directive containing the todo.html :
<md-list-item layout='row' layout-sm='column' layout-align='center center' layout-wrap>
<i class='material-icons md-avatar'>border_color</i>
<div class='md-list-item-text'><h3>{{mainCtrl.text}}</h3></div>
<div class='md-secondary'>
<md-button class='md-fab md-primary md-small box red-btn'
aria-label='delete' ng-click='mainCtrl.deleteTodo(mainCtrl.index)'>
<i class='material-icons small-icon'>highlight_off</i>
</md-button>
</div>
</md-list-item>
Where todo.directive.js :
(function () {
'use strict';
angular
.module('todoApp')
.directive('acmeTodo', acmeTodo);
function acmeTodo() {
var directive = {
restrict: 'EA',
scope: {
text : '=',
index : '='
},
templateUrl: 'todo.html',
controller : 'MainController',
controllerAs : 'mainCtrl',
bindToController : true
};
return directive;
}
})();
Finally, main.controller.js :
(function () {
'use strict';
angular
.module('todoApp')
.controller('MainController', MainController);
function MainController() {
var vm = this;
vm.todos = [];
. . .
vm.addToDo = addToDo;
vm.deleteTodo = deleteTodo;
//vm.todo.content is the ng-model of the input-box
function addToDo() {
if( vm.todo && !_.isUndefined(vm.todo.content)){
pushNewToDo(vm.todo.content);
}
}
function deleteTodo(index) {
vm.todos.splice(index, 1);
}
function pushNewToDo(todo) {
vm.todos.push({ content : todo });
vm.todo.content = '';
}
}
})();
Everything works fine except for todo deletion. When
deleteTodo
, the function correctly accepts external ones$index
from mainng-repeat
, but I cannot find out why, it isvm.todos
empty at this moment, so nothing is deleted.
If instead I can manage to move all of the todo.html content to acme-todo
, everything works fine.
I also tried setting $scope : true
in directive instead of passing both text
and $index
but I am still facing the same problem.
Here is a working Codepen that reproduces my problem. Notabene In CodePen I use template
instead templateUrl
, and I changed the icons just to work correctly there.
Here's the real app screen:
I know that by default, if I don't specify any controller, the directive will still select its scope, but
EDIT
Using Service
or Factory
also solves the problem as in this CodePen solves the problem, but I feel like I am adding too much logic for such a small thing.
Why am I getting an empty todos array, even thinking that both the controller and the directive share the same scope? How can I fix this while maintaining the same approach (using the todo directive)?
source to share
You have to separate the application controller and directives because when you initialize a directive you are creating a new controller, so a new locator $scope
and a new one todos
locally inside the directive. After that, you can pass the delete function from the main controller to the directive $scope
.
Take a look here: http://codepen.io/anon/pen/zZWyLV
source to share