Have you implemented OpenMRS? Please participate in the Implementation Site Survey. If you already have, thank you!
Skip to end of metadata
Go to start of metadata

We like the ngDialog plugin, which makes nice-looking dialogs, and they're quite easy to do. We have included styling for it in the uicommons module under the default theme (ngdialog-theme-default).

Usage example, for a Confirm dialog:

GSP view using a dialog
<%
    ui.includeJavascript("uicommons", "angular.js")
    ui.includeJavascript("uicommons", "ngDialog/ngDialog.js")
    ui.includeCss("uicommons", "ngDialog/ngDialog.min.css")
    // you also need to have included referenceapplication.css or similar, which usually happens globally through the distribution
 
    // also include your page's js
%>
 
<div id="your-page-app" ng-controller="YourPageCtrl">
    <script type="text/ng-template" id="dialogTemplate">
        <div class="dialog-header">
            <h3>Doing something</h3>
        </div>
        <div class="dialog-content">
            <div>
                Why? <input type="text" ng-model="reason"/>
                {{ ngDialogData.helperData }}
            </div>
            <div>
                <button class="confirm right" ng-click="confirm(reason)">${ ui.message("uicommons.save") }</button>
                <button class="cancel" ng-click="closeThisDialog()">${ ui.message("uicommons.cancel") }</button>
            </div>
        </div>
    </script>
 
    <a ng-click="showDialog()">
        <i class="icon-plus-sign"></i>
        Show dialog
    </a>
</div>
 
<script type="text/javascript">
    // manually bootstrap angular app, in case there are multiple angular apps on a page
    angular.bootstrap('#your-page-app', ['yourpageapp']);
</script>

 

The JavaScript backing this is:

angular.module('yourpageapp', ['ngDialog']). // make sure to declare a dependency on ngDialog in your app
 
controller('YourPageCtrl', ['$scope', 'ngDialog',
function($scope, ngDialog) {
    $scope.showDialog = function() {
        ngDialog.openConfirm({
            showClose: false,
            closeByEscape: true,
            closeByDocument: true,
            data: angular.toJson({
                helperData: "One way to push data into the dialog"
            }),
            template: 'dialogTemplate' // in this example we defined this inline with <script type="ng-template"> but you can also give a url
        }).then(function(reason) {
            console.log("They chose reason: " + reason);
        }, function() {
            console.log("They clicked cancel");
        });
    };
}]);

 

Advanced

There are a several different ways to pass data into the dialog from the enclosing controller, each of which you might use at different times:

Using "data"

Pro: Cleaner JavaScript code.

Con: Annoying need to refer to "ngDialogData" in the view. Could be expensive for a huge data model.

Pushing data into the dialog with 'data'
confirmDeleteRelationship = function(rel) {
    ngDialog.openConfirm({
        data: angular.toJson({
            relationship: rel
        })
        template: "..."
    });
}
 
// in the view you can do something like this:
//   {{ ngDialogData.relationship.personA }} is related
//   via {{ ngDialogData.relationship.relationshipType.display }}
//   to {{ ngDialogData.relationship.personB }}

 

Using "scope"

Pro: Cleaner view code. More control and power.

Con: Non-obvious boilerplate JavaScript

Pushing data into the dialog with a custom scope
$scope.helperFunction = function(x) { return "something" };
 
confirmDeleteRelationship = function(rel) {
    var dialogScope = $scope.$new();  // Doing $scope.$new(true) instead gives an isolated scope (with no access to helperFunction)
    angular.extend(dialogScope, {
        relationship: rel
    });
    ngDialog({
        scope: dialogScope,
        template: "..."
    })
    .finally(function() {
        dialogScope.$destroy(); // I assume you need to do this to avoid leaking resources
    });
}

// in the view you can do something like this:
//   {{ relationship.personA }} is related
//   via {{ relationship.relationshipType.display }}
//   to {{ relationship.personB }}
//
// and you can also access
//   {{ helperFunction(relationship) }}

 

Using a controller

Pro: this is the best (I hadn't tried it yet when I wrote all the above)

It works something like this (I haven't actually tested this code)

confirmDeleteRelationship = function(rel) {
    ngDialog({
        controller: ["$scope", function($scope) { // you can also inject a service with helper functions
			$scope.relationship = rel;
		}],
        template: "..."
    });
}
 
// in the view you can do something like this:
//   {{ relationship.personA }} is related
//   via {{ relationship.relationshipType.display }}
//   to {{ relationship.personB }}

 

 

  • No labels