Brian
Brian

Reputation: 38035

How do I use an Angular directive to show a dialog?

Using Angular, I'm trying to create a directive that will be placed on a button that will launch a search dialog. There are multiple instances of the search button, but obviously I only want a single instance of the dialog. The dialog should be built from a template URL and have it's own controller, but when the user selects an item, the directive will be used to set the value.

Any ideas on how to create the dialog with it's own controller from the directive?

Here's what I've go so far (basically just the directive)...

http://plnkr.co/edit/W9CHO7pfIo9d7KDe3wH6?p=preview

Here is the html from the above plkr...

<a href="" my-find="setPerson">Find</a>

Here is the code from the above plkr...

var app = angular.module('plunker', []);

app.controller('MainCtrl', function($scope) {
  var person = {};
  person.name = 'World';
  $scope.person = person;

  $scope.setPerson = function(newPerson) {
    person = newPerson;
    $scope.person = person;
  }
});

app.directive('myFind', function () {

    var $dlg; // holds the reference to the dialog. Only 1 per app.

    return {
        restrict: 'A',
        link: function (scope, el, attrs) {

            if (!$dlg) {
                //todo: create the dialog from a template.
                $dlg = true;
            }

            el.bind('click', function () {

                //todo: use the dialog box to search.

                // This is just test data to show what I'm trying to accomplish.
                alert('Find Person'); 
                var foundPerson = {};
                foundPerson.name = 'Brian';
                scope.$apply(function () {
                    scope[attrs.myFind](foundPerson);
                });

            });
        }
    }
})

This is as far as I've gotten. I can't quite figure out how to create the dialog using a template inside the directive so it only occurs once and then assign it a controller. I think I can assign the controller inside the template, but first I need to figure out how to load the template and call our custom jQuery plugin to generate the dialog (we have our own look & feel for dialogs).

So I believe the question is, how do I load a template inside of a directive? However, if there is a different way of thinking about this problem, I would be interested in that as well.

Upvotes: 1

Views: 1372

Answers (2)

SomeoneHelpful
SomeoneHelpful

Reputation: 86

I recommend this plugin:

https://github.com/trees4/ng-modal

Demo here: https://trees4.github.io/ngModal/demo.html

Create a dialog declaratively; and it works with existing controllers. The content of the dialog can be styled however you like.

Upvotes: 0

artur grzesiak
artur grzesiak

Reputation: 20348

I will show you how to do it using bootstrap-ui. (you can modify it easily, if it does not suit your needs).

Here is a skeleton of the template. You can normally bound to any properties and functions that are on directive's scope:

<div class="modal-dialog">
    <div class="modal-content">
        <div class="modal-header">
           ... // e.g. <div class="button" ng-click=cancel()></div>
        </div>
        <div class="modal-body">
           ...
        </div>
        <div class="modal-footer">
           ...
        </div>
    </div>
</div>

Here is how to create/declare directive in your module:

 .directive("searchDialog", function ($modal) {

        return {

            controller: SearchDialogCtrl,

            scope : {
                searchDialog: '=' // here you will set two-way data bind with a property from the parent scope
            },

            link: function (scope, element, attrs) {

                element.on("click", function (event) { // when button is clicked we show the dialog
                    scope.modalInstance = $modal.open({
                        templateUrl: 'views/search.dialog.tpl.html',
                        scope: scope // this will pass the isoleted scope of search-dialog to the angular-ui modal
                    });
                    scope.$apply();
                });
            }
        }
    });

Then controller may look something like that:

function SearchDialogCtrl(dep1, dep2) {

    $scope.cancel = function() {
        $scope.modalInstance.close(); // the same instance that was created in element.on('click',...)
    }

    // you can call it from the template:  search.dialog.tpl.html
    $scope.someFunction = function () { ... }

    // it can bind to it in the search.dialog.tpl.html
    $scope.someProperty;

    ...

    // this will be two-way bound with some property from the parent field (look below)
    // if you want to perform some action on it just use $scope.$watch
    $scope.searchDialog;
}

Then it your mark-up you can just use it like that:

<div class="buttonClass" search-dialog="myFieldFromScope">search</div>

Upvotes: 1

Related Questions