crmConfirm - Allow confirmation dialogs using Angular partials
[civicrm-core.git] / js / angular-crm-ui.js
index f055ca6c7d6c3dd7d4c8caafebb3962af24e8ded..7dd588aeda58ea5947460a544c91971faeb12bf0 100644 (file)
       };
     })
 
+    // Render a crmEntityRef widget
+    // usage: <input crm-entityref="{entity: 'Contact', select: {allowClear:true}}" ng-model="myobj.field" />
+    .directive('crmEntityref', function ($parse, $timeout) {
+      return {
+        require: '?ngModel',
+        scope: {
+          crmEntityref: '='
+        },
+        link: function (scope, element, attrs, ngModel) {
+          // In cases where UI initiates update, there may be an extra
+          // call to refreshUI, but it doesn't create a cycle.
+
+          ngModel.$render = function () {
+            $timeout(function () {
+              // ex: msg_template_id adds new item then selects it; use $timeout to ensure that
+              // new item is added before selection is made
+              element.select2('val', ngModel.$viewValue);
+            });
+          };
+          function refreshModel() {
+            var oldValue = ngModel.$viewValue, newValue = element.select2('val');
+            if (oldValue != newValue) {
+              scope.$parent.$apply(function () {
+                ngModel.$setViewValue(newValue);
+              });
+            }
+          }
+
+          function init() {
+            // TODO watch options
+            // TODO can we infer "entity" from model?
+            element.crmEntityRef(scope.crmEntityref || {});
+            element.on('change', refreshModel);
+            $timeout(ngModel.$render);
+          }
+
+          init();
+        }
+      };
+    })
+
     // example <div crm-ui-tab crm-title="ts('My Title')">...content...</div>
     // WISHLIST: use a full Angular component instead of an incomplete jQuery wrapper
     .directive('crmUiTab', function($parse) {
 
     // Example: <button crm-confirm="{message: ts('Are you sure you want to continue?')}" on-yes="frobnicate(123)">Frobincate</button>
     // Example: <button crm-confirm="{type: 'disable', obj: myObject}" on-yes="myObject.is_active=0; myObject.save()">Disable</button>
-    .directive('crmConfirm', function () {
+    // Example: <button crm-confirm="{templateUrl: '~/path/to/view.html', export: {foo: bar}}" on-yes="frobnicate(123)">Frobincate</button>
+    .directive('crmConfirm', function ($compile, $rootScope, $templateRequest, $q) {
       // Helpers to calculate default options for CRM.confirm()
       var defaultFuncs = {
         'disable': function (options) {
           };
         }
       };
+      var confirmCount = 0;
       return {
         link: function (scope, element, attrs) {
           $(element).click(function () {
               options.title = attrs.title;
             }
             var defaults = (options.type) ? defaultFuncs[options.type](options) : {};
+
+            var tpl = null, stubId = null;
+            if (!options.message) {
+              if (options.templateUrl) {
+                tpl = $templateRequest(options.templateUrl);
+              }
+              else if (options.template) {
+                tpl = options.template;
+              }
+              if (tpl) {
+                stubId = 'crmUiConfirm_' + (++confirmCount);
+                options.message = '<div id="' + stubId + '"></div>';
+              }
+            }
+
             CRM.confirm(_.extend(defaults, options))
-              .on('crmConfirm:yes', function () { scope.$apply(attrs.onYes); })
-              .on('crmConfirm:no', function () { scope.$apply(attrs.onNo); });
+              .on('crmConfirm:yes', function() { scope.$apply(attrs.onYes); })
+              .on('crmConfirm:no', function() { scope.$apply(attrs.onNo); });
+
+            if (tpl && stubId) {
+              $q.when(tpl, function(html) {
+                var scope = options.scope || $rootScope.$new();
+                if (options.export) {
+                  angular.extend(scope, options.export);
+                }
+                var linker = $compile(html);
+                $('#' + stubId).append($(linker(scope)));
+              });
+            }
           });
         }
       };