I'm having a pretty tricky problem that seems to be trivial but I'm not finding a good way to solve it.
Essentially, I'm building a todo list application using Angular and Angular-Material.
I have a 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 a directive which contains a 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;
}
})();
And 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 when deleting a todo. When
deleteTodo
is called, the function correctly receives external$index
from main'sng-repeat
but, can't find out why,vm.todos
is empty at that moment, so, nothing gets deleted.
If, instead, I manage to move all of todo.html content at acme-todo
place's everything works fine.
I also tried setting $scope : true
in the directive instead of passing both text
and $index
but I'm still encountering the same problem.
Here is a working Codepen which reproduces my issue. N.B. On the CodePen I'm using template
instead of templateUrl
and I changed the icons just to make things work properly there.
Here's a screen of the real application:
I know that, by default, if I do not specify any controller, the directive will still pick its scope, but
EDIT
Using a Service
or a Factory
also solves the problem like in this CodePen solves the problem, but I feel like adding way too much logic for such a small thing.
Why Am I getting an empty todos array even thought both controller and directive share the same scope? How can I fix that keeping the same approach (using a todo directive)?