Search code examples
angularjsangularjs-material

AngularJS - moving Material mdDialog to service


I'm trying to cleanup code of one of my controllers which became too big. First I have decided to move attendee registration, which uses AngularJS Material mdDialog, to the service.

Original (and working) controller code looks like:

myApp.controller('RegistrationController', ['$scope','$routeParams','$rootScope','$location','$filter','$mdDialog', function($scope, $routeParams, $rootScope, $location, $filter, $mdDialog){

    var attendee = this;
    attendees = [];
...

    $scope.addAttendee = function(ev) {
        $mdDialog.show({
        controller: DialogController,
        templateUrl: 'views/regForm.tmpl.html',
        parent: angular.element(document.body),
        targetEvent: ev,
        clickOutsideToClose:true,
        controllerAs: 'attendee',
        fullscreen: $scope.customFullscreen, // Only for -xs, -sm breakpoints.
        locals: {parent: $scope}
    })
    .then(function(response){
        attendees.push(response);

        console.log(attendees);
        console.log(attendees.length);
    })
  };

    function DialogController($scope, $mdDialog) {

        var attendee = this;

        $scope.hide = function() {
            $mdDialog.hide();
        };

        $scope.cancel = function() {
            $mdDialog.cancel();
        };

        $scope.save = function(response) {
            $mdDialog.hide(response);
        };
    }

}]);

and the code for the controller after separation:

myApp.controller('RegistrationController', ['$scope','$routeParams','$rootScope','$location','$filter','$mdDialog','Attendees', function($scope, $routeParams, $rootScope, $location, $filter, $mdDialog, Attendees){

...


    $scope.attendees= Attendees.list();

    $scope.addAttendee = function (ev) {
        Attendees.add(ev);
    }

    $scope.deleteAttendee = function (id) {
        Attendees.delete(id);
    }

}]);

New service code looks like:

myApp.service('Attendees', ['$mdDialog', function ($mdDialog) {
    //to create unique attendee id
    var uid = 1;

    //attendees array to hold list of all attendees
    var attendees = [{
        id: 0,
        firstName: "",
        lastName: "",
        email: "",
        phone: ""
    }];

    //add method create a new attendee
    this.add = function(ev) {
        $mdDialog.show({
        controller: DialogController,
        templateUrl: 'views/regForm.tmpl.html',
        parent: angular.element(document.body),
        targetEvent: ev,
        clickOutsideToClose:true,
        controllerAs: 'attendee',
        fullscreen: this.customFullscreen, // Only for -xs, -sm breakpoints.
        //locals: {parent: $scope}
    })
    .then(function(response){
        attendees.push(response);

        console.log(attendees);
        console.log(attendees.length);
    })
  };

    //simply search attendees list for given id
    //and returns the attendee object if found
    this.get = function (id) {
        for (i in attendees) {
            if (attendees[i].id == id) {
                return attendees[i];
            }
        }

    }

    //iterate through attendees list and delete 
    //attendee if found
    this.delete = function (id) {
        for (i in attendees) {
            if (attendees[i].id == id) {
                attendees.splice(i, 1);
            }
        }
    }

    //simply returns the attendees list
    this.list = function () {
        return attendees;
    }

    function DialogController($mdDialog) {

        this.hide = function() {
            $mdDialog.hide();
        };

        this.cancel = function() {
            $mdDialog.cancel();
        };

        this.save = function(response) {
            $mdDialog.hide(response);
        };
    }

}]);

but I'm not able to "save" from the spawned mdDialog box which uses ng-click=save(attendee) neither close the dialog box.

What I'm doing wrong?


Solution

  • I'm not able to "save" from the spawned mdDialog box which uses ng-click=save(attendee) neither close the dialog box.

    When instantiating a controller with "controllerAs" syntax, use the name with which it is instantiated:

    <button ng-click="ctrl.save(ctrl.attendee)">Save</button>
    
    this.add = function(ev) {
        $mdDialog.show({
        controller: DialogController,
        templateUrl: 'views/regForm.tmpl.html',
        parent: angular.element(document.body),
        targetEvent: ev,
        clickOutsideToClose:true,
        controllerAs:  ̶'̶a̶t̶t̶e̶n̶d̶e̶e̶'̶ 'ctrl',
        fullscreen: this.customFullscreen, // Only for -xs, -sm breakpoints.
        //locals: {parent: $scope}
    })
    .then(function(response){
        attendees.push(response);
    
        console.log(attendees);
        console.log(attendees.length);
        return response;     
    });
    

    To avoid confusion, choose a controller instance name that is different from the data names.