Material: $mdDialog.show(): controller option should be allowed to be a string, referencing a controller present on the current module

Created on 5 Jan 2015  路  6Comments  路  Source: angular/material

Right now, when opening a custom dialog, you have to pass a controller as a function.

But with what I'm doing, which is possibly opening a dialog from another dialog, this would start to get messy. What I want to do is reference a controller for the new dialog by a string with its name on the module.

I really don't see a reason why this wouldn't possible, as a good framework always has to be prepared for all valid possibilities, and I believe this to be one of those :)

enhancement

Most helpful comment

This seems to be working for me on v0.7.0-rc1.
I'm currently using this approach to display a list of photos via a custom dialog.
See example code below.

//EXAMPLE:
// Declare app level module which depends on views, and components

    angular.module('myApp', [
            'ngRoute',
            'ngMaterial',
            'ngMessages',
            'ngSanitize',
            'ngTouch',
            'myApp.dashboard',
            'myApp.expense',
            'myApp.user',
            'myApp.trip',
            'myApp.version'
        ])
        .config(config)
        .controller('MainController', MainController);

//main controller implementation not shown

//Dialog VM Controller

angular.module('myApp')
        .controller('PhotoViewerController', PhotoViewerController);
    PhotoViewerController.$inject = ['$mdDialog', 'photos'];

    function PhotoViewerController($mdDialog, photos) {
        var vm = this;
        vm.photos = photos;
        vm.ok = ok;

        function ok() {
            // Easily hides most recent dialog shown...
            // no specific instance reference is needed.
            $mdDialog.hide();
        }
    }

// Expense VM Controller

  angular.module('myApp.expense', ['ngMaterial'])
        .controller('ExpenseController', ExpenseController);

    ExpenseController.$inject = ['$mdDialog',  'photoService'];

    function ExpenseController($mdDialog, photoService) {
        var vm = this;
        vm.photos = photoService.getPhotos();
        vm.showPictures = showPictures;

        function showPictures($event) {
            $mdDialog.show({
                targetEvent: $event,
                templateUrl: 'html/dialogs/picture-dialog.tpl.html',
                controller: 'PhotoViewerController',
                controllerAs: 'photoViewerVm',
                locals: {
                    photos: vm.photos
                }
            });
        }
    }

//In Expense.tpl.html

<md-content ng-controller="ExpenseController as expVm">
        <md-button ng-click="expVm.showPictures($event)">Show Pic Dialog</md-button>
</md-content>

//picture-dialog.tpl.html

<md-dialog aria-label="Photos">
    <md-content layout-fill>
        <md-progress-circular layout-fill md-mode="indeterminate" ng-hide="photoViewerVm.photos.length > 0"></md-progress-circular>
        <section  ng-repeat="photo in photoViewerVm.photos">
           <md-divider class="md-primary">{{photo.name}}</<md-divider>
            <img layout-fill ng-src="{{photo.data}}" />
        </section>
    </md-content>
    <div class="md-actions" layout="row">
        <md-button ng-click="photoViewerVm.ok()">
            OK
        </md-button>
    </div>
</md-dialog>

All 6 comments

This seems to be working for me on v0.7.0-rc1.
I'm currently using this approach to display a list of photos via a custom dialog.
See example code below.

//EXAMPLE:
// Declare app level module which depends on views, and components

    angular.module('myApp', [
            'ngRoute',
            'ngMaterial',
            'ngMessages',
            'ngSanitize',
            'ngTouch',
            'myApp.dashboard',
            'myApp.expense',
            'myApp.user',
            'myApp.trip',
            'myApp.version'
        ])
        .config(config)
        .controller('MainController', MainController);

//main controller implementation not shown

//Dialog VM Controller

angular.module('myApp')
        .controller('PhotoViewerController', PhotoViewerController);
    PhotoViewerController.$inject = ['$mdDialog', 'photos'];

    function PhotoViewerController($mdDialog, photos) {
        var vm = this;
        vm.photos = photos;
        vm.ok = ok;

        function ok() {
            // Easily hides most recent dialog shown...
            // no specific instance reference is needed.
            $mdDialog.hide();
        }
    }

// Expense VM Controller

  angular.module('myApp.expense', ['ngMaterial'])
        .controller('ExpenseController', ExpenseController);

    ExpenseController.$inject = ['$mdDialog',  'photoService'];

    function ExpenseController($mdDialog, photoService) {
        var vm = this;
        vm.photos = photoService.getPhotos();
        vm.showPictures = showPictures;

        function showPictures($event) {
            $mdDialog.show({
                targetEvent: $event,
                templateUrl: 'html/dialogs/picture-dialog.tpl.html',
                controller: 'PhotoViewerController',
                controllerAs: 'photoViewerVm',
                locals: {
                    photos: vm.photos
                }
            });
        }
    }

//In Expense.tpl.html

<md-content ng-controller="ExpenseController as expVm">
        <md-button ng-click="expVm.showPictures($event)">Show Pic Dialog</md-button>
</md-content>

//picture-dialog.tpl.html

<md-dialog aria-label="Photos">
    <md-content layout-fill>
        <md-progress-circular layout-fill md-mode="indeterminate" ng-hide="photoViewerVm.photos.length > 0"></md-progress-circular>
        <section  ng-repeat="photo in photoViewerVm.photos">
           <md-divider class="md-primary">{{photo.name}}</<md-divider>
            <img layout-fill ng-src="{{photo.data}}" />
        </section>
    </md-content>
    <div class="md-actions" layout="row">
        <md-button ng-click="photoViewerVm.ok()">
            OK
        </md-button>
    </div>
</md-dialog>

@nross63 - plz do not post large code sections into Issues; use a CodePen or Plunkr. Thank you.

This has worked in all my tests. If it's not working, your controller is not declared properly.

I tried it again, made sure everything was set up correctly. I still get this error: https://docs.angularjs.org/error/ng/areq?p0=bookmark-icon-dialog-controller&p1=not%20a%20function,%20got%20undefined

It seems to me $mdDialog was expecting a function and can't understand the string with the controller name. Version is 0.7.0-rc2

@MarcosPortugal - plz provide a CodePen or Plunkr that manifests this issue. We will reopen and investigate at that point.

Oh sorry about that. I was mentioning the controller using hyphens instead of camel case. In my defense, this case switching stuff with angular is quite confusing and can go unnoticed :smile:

Was this page helpful?
0 / 5 - 0 ratings

Related issues

WebTechnolog picture WebTechnolog  路  3Comments

reggiepangilinan picture reggiepangilinan  路  3Comments

sbondor picture sbondor  路  3Comments

ghost picture ghost  路  3Comments

PeerInfinity picture PeerInfinity  路  3Comments