ng-click on user defined $mdDialog with external template are not working

Viewed 1397

working the first time with $mdDialog I am used to create a dialog with an external HTML Template.

So far, so good,... it works template can get opened, but ng-click in the html wont work anymore.

And I cannot find the reason for it.

The mdDialog gets called in userController like this:

<md-icon
        layout="row"
        flex md-font-set="material-icons"
        class="active"
        ng-click="vm.showMenu($event)">
    menu
</md-icon>

The method to open the $mdDialog in userController:

vm.showMenu = function showMenu(ev){

    $mdDialog.show({
        controller: MenuDialogController,
        templateUrl: 'app/components/head/user/menu.dialog.html',
        parent: angular.element($document.body),
        targetEvent: ev,
        clickOutsideToClose:true,
        fullscreen: $scope.customFullscreen // Only for -xs, -sm breakpoints.
    })
        .then(function(answer) {
            $scope.status = 'You said the information was "' + answer + '".';
        }, function() {
            $scope.status = 'You cancelled the dialog.';
        });
};

And this is the dialog controller for the dialog, where the buttons are not working:

angular
    .module('trax')
    .controller('MenuDialogController', MenuDialogController);

function MenuDialogController() {

    var vm = this;

    vm.close = function close(){
        alert('close clicked');
    }

    vm.ok = function ok(){
        alert('ok clicked');
    }

}

And this is the html code for the dialogController:

<md-dialog aria-label="User Menu">
    <form ng-cloak>
        <md-toolbar>
            <div class="md-toolbar-tools">
                <h2>User Menu</h2>
                <span flex></span>
                <md-button class="md-icon-button" ng-click="vm.close($event)">
                    <md-icon md-font-set="material-icons">close</md-icon>
                </md-button>
            </div>
        </md-toolbar>

        <md-dialog-content>
            <div class="md-dialog-content">
                <h2>Dialog Title</h2>
                <p>Dialog Text....</p>
                <p ng-click="vm.test($event)">test</p>
            </div>
        </md-dialog-content>

        <md-dialog-actions layout="row">
            <md-button href="http://en.wikipedia.org/wiki/Mango" target="_blank" md-autofocus>
                More on Wikipedia
            </md-button>
            <span flex></span>
            <md-button ng-click="vm.close($event)">
                cancel
            </md-button>
            <md-button ng-click="vm.ok($event)">
                ok
            </md-button>
        </md-dialog-actions>
    </form>
</md-dialog>

None of the ng-clicks is working!

Any hint for me?

3 Answers

To leave your code unmodified you have to add after

var vm = this;

with

var vm = this;
$scope.vm = vm;

In this way you can use it in your template.

Another way is declare the methods directly in $scope as

$scope.close = function() { ... };
$scope.ok = function() { ... };

The first method is equal to declare controllerAs: "vm" in $mdDialog.show helper method

    angular
    .module('trax')
    .controller('MenuDialogController', MenuDialogController);

function MenuDialogController() {

    var vm = this;

    //Here change vm to $scope
    $scope.close = function close(){
        alert('close clicked');
    }

    $scope.ok = function ok(){
        alert('ok clicked');
    }

}

You have to assign your funcs to the $scope of your dialog controller

It appears thet your setup it slightly off. In fact, it seems to be that you wish to pass the scope into this dialog. Taken from the examples at the $mdDialog docs I was able to find the following...

// Dialog #3 - Demonstrate use of ControllerAs and passing $scope to dialog
//             Here we used ng-controller="GreetingController as vm" and
//             $scope.vm === <controller instance="">

It looks like you'll need to modify your implementation to match this pattern. Try the following...

$mdDialog.show({
  controller: MenuDialogController,
  templateUrl: 'app/components/head/user/menu.dialog.html',
  parent: angular.element($document.body),
  targetEvent: ev,
  clickOutsideToClose:true,
  fullscreen: $scope.customFullscreen,
  scope: $scope,         // use parent scope in template
  preserveScope: true,   // do not forget this if use parent scope
}).then(function(answer) {
  $scope.status = 'You said the information was "' + answer + '".';
}, function() {
  $scope.status = 'You cancelled the dialog.';
});

Notice the scope and preserveScope options specified.

// Since MenuDialogController is instantiated with ControllerAs syntax
// AND we are passing the parent '$scope' to the dialog, we MUST
// use 'vm.<xxx>' in the template markup
Related