0

I am display a modal where if the user click on delete button I want to call delete() from controller A inside controller B

enter image description here

I am refactoring the Todo App example code at AngularJS website (based on what I have learned so far) https://jsfiddle.net/api/post/library/pure/

my full project on github https://github.com/ahmadssb/Angular-Todo-App/tree/development

app.js

angular.module('todoApp', [
    // modules
    'ui.bootstrap', 
    'ui.bootstrap.modal',

    // controllers
    'todo-list-controller', 
    'modal-controller',
    'modal-instance-controller',

    // directives
    'todo-list-directive'
    // services

]);

todo-list-controller.js

angular.module('todo-list-controller', [])
    .controller('TodoListController', function ($scope, $http) {
        var self = this;
        self.todoList = [];
        $http.get("data/todos.json")
            .success(function (response) {
                self.todoList = response;
            });
        $scope.numberOfdeletedNotes = function () {
            var count = 0;
            angular.forEach(self.todoList, function (todo) {
                count += todo.done ? 1 : 0;
            });
            console.log(count);
            return count;
        };
        $scope.delete = function () {
            var currentTodoList = self.todoList;
            self.todoList = [];
            angular.forEach(currentTodoList, function (todo) {
                if (!todo.done) self.todoList.push(todo);
            });
        };
    });

modal-controller.js

angular.module('modal-controller', [])
    .controller('ModalController', function ($scope, $uibModal, $log) {

        $scope.animationsEnabled = true;

        $scope.open = function (size) {
            var modalInstance = $uibModal.open({
                animation: $scope.animationsEnabled,
                templateUrl: 'templates/modals/delete-modal.html',
                controller: 'ModalInstanceController',
                size: size,
            });
            console.log('open()');
        };
    });

modal-instance-controller.js

angular.module('modal-instance-controller', [])
    .controller('ModalInstanceController', function ($scope, $modalInstance) {
        $scope.ok = function () {
            // I would like to call delete() from todo-list-controller.js
            $modalInstance.close($scope.$parent.delete());
        };

        $scope.cancel = function () {
            $modalInstance.dismiss('cancel');
        };
    });

delete-modal.html

<div class="modal-header">
    <h3 class="modal-title">Warning!</h3>
</div>
<div class="modal-body" ng-control="TodoListController as todoList">
    <h4>You are about to delete <span><i> {{$scope.$parent.numberOfdeletedNotes()}} </i></span> notes</h4>
</div>
<div class="modal-footer">
    <button class="btn btn-danger" type="button" ng-click="ok()">Delete</button>
    <button class="btn btn-warning" type="button" ng-click="cancel()">Cancel</button>
</div>

todo-list-template.html

[![<div class="col-md-12" ng-controller="TodoListController as todoList">
    <h2>TODO App</h2>
    <div class="todoList">
        <span class="numberOfList" ng-controller='ModalController as modal'>
         {{remaining()}} of {{todoList.todoList.length}} remaining  
         <button class="btn-danger btn" ng-click="open()">Delete</button>
         </span>
        <ul class="list" ng-repeat="todo in todoList.todoList">
            <li class="item">
                <input type="checkbox" ng-model="todo.done">&nbsp;
                <span class="todo-{{todo.done}}">{{todo.text}} - {{todo.done}} </span>
            </li>
        </ul>
    </div>
    <div class="newTask">
        <form class="form-group" ng-submit="addTodo()">
            <feildset>
                <input type="text" size="30" class="form-control" ng-model="text">
                <input type="submit" value="submit" class="btn btn-primary">
            </feildset>
        </form>
    </div>
</div>]
Ahmad Saleh
  • 879
  • 2
  • 10
  • 20
  • 3
    if you need functionality from another controller think about making it a service https://docs.angularjs.org/guide/services – messerbill Oct 22 '15 at 12:01
  • Could you specify a little bit more about the problem? Maybe publish some JSFiddle with the error, so we can understand better. Besides that, I think the functions Broadcast and Emit will come handy – sailens Oct 22 '15 at 12:01
  • Possible duplicate of [AngularJS : How can I pass variables between controllers?](http://stackoverflow.com/questions/12008908/angularjs-how-can-i-pass-variables-between-controllers) – hurricane Oct 22 '15 at 12:12
  • 1
    @messerbill thank you I am reading about services now, I'll try to solve my issue – Ahmad Saleh Oct 22 '15 at 12:41
  • try to implement it and update this question if you are still in trouble – messerbill Oct 22 '15 at 12:43

1 Answers1

3

What you need to do is move any state, and state related functions you have outside of your controller to a service. In your case, it could be good to create a TodoListService that manages a todo list, and can be injected anywhere. For example:

.service('TodoListService', function($http){
    var state = {
        todoList: []
    };
    $http.get("data/todos.json")
        .success(function (response) {
            state.todoList = response;
        });

    // add and expose any functions that let you manipulate your todolist here as well

    return {
        getState: function(){ return state; }
    }
});

Now you can inject TodoListService into any controller (or anywhere), and read/manipulate the todo list as you please.

Matt Way
  • 32,319
  • 10
  • 79
  • 85
  • Controllers are not supposed to share state or anything else in between each other, the better solution would be to provide a service. – orbatschow Oct 22 '15 at 12:05
  • 3
    Whooops, it was supposed to be a comment under the question :/ You're absolutely right, sorry. – orbatschow Oct 22 '15 at 12:06
  • I am reading about services now and i'll try to implement your answer , from what I have read I must move delete() function into the return of service() after getState: function(){...} – Ahmad Saleh Oct 22 '15 at 12:39
  • 1
    Yes, exactly. Add any functions you want that will effect the todo list. And in your controllers bind like this: `$scope.todoState = TodoListService.getState();`. – Matt Way Oct 22 '15 at 13:04
  • 1
    @MattWay the function is working but I can check if it is correct from console because I cannot call it in html (I thank I can solve this just need to debug my code) – Ahmad Saleh Oct 22 '15 at 13:24