2

What I'm trying to do is to add a bit of Angular within alertifyjs prompt.

I have this directive:

angular.module('items').directive('cancelItem', ['$rootScope', 'Items', function ($rootScope, Items) {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {
      var item_id = attrs.cancelItem;
      element.bind('click', function (event) {
        event.stopPropagation();
        alertify.prompt(
          'Warning!',
          function (e, reason) {
            if (reason === '') { 
              e.cancel = true;
            } else {
              var data = {
                id: cancel_id,
                data: {
                  action: 'cancel'
                }
              };
              Items.update({ 
                id: item_id
              }, data)
              .$promise.then(function (data) {
                alertify.success('Item ' + item_id + ' has been cancelled');
                $rootScope.$broadcast('Item cancelled');
              });
            }
          },
          function () {
            return;
          }
        )
        .setContent(
          '<p>Are you sure you wish to CANCEL the item ' + item_id + '?</p>' +
          '<select class="ajs-input" ng-model="reason">' + 
          '<option ng-value="Reason 1">Option one</option>' + 
          '<option ng-value="Reason 2">Option two</option>' + 
          '<option ng-value="Reason 3">Option three</option>' + 
          '</select>' + 
          '<input class="ajs-input" type="text" ng-bind="reason">'
        );
      });

      scope.$on('$destroy', function() {
        element.unbind();
      });
    }
  };
}]);

As you can see I'm trying to inject some angularjs inside the .setContent() method of alertify and it doesn't work.

I would like to understand how to let it work...

Alertify prompt offer you only a text input and I would like to replace it with a select to bind the result value to the original alertify text input that will be hidden in future.

It doesn't update the select value to the text input.

Plunker

FINAL WORKING CODE:

I used a different approach with Alertifyjs, complete code is here:

'use strict';

angular.directive('cancelItem', ['$rootScope', '$compile',
function ($rootScope, $compile) {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {

      var item_id = attrs.cancelItem;
      var templateElement = '<p>Are you sure you wish to CANCEL the item ' + item_id + '?</p>' +
        '<select class="ajs-input form-control" ng-init="reason = options[0]" ng-model="reason" ng-options="option for option in options"></select>' + 
        '<input ng-show="reason == options[10]" class="ajs-input" type="text" ng-model="otherReason" placeholder="Enter custom reason">' + 
        '<input ng-hide="true" class="ajs-input" type="text" ng-value="reason == options[10] ? otherReason : reason" ng-value="reason || otherReason">';

      scope.reason = '';
      scope.otherReason = '';
      scope.options = [
        'Option one',
        'Option two',
        'Option three',
        'Other'
      ];

      element.bind('click', function (event) {
        event.stopPropagation();
        alertify.prompt()
        .set({
          onshow: function () {
            this.setHeader('Warning!');
            this.setContent(templateElement);
            var template = angular.element(document.querySelector('.alertify'));
            $compile(template)(scope);
            scope.$digest();
          },
          onok: function (e) {
            if (scope.reason === '' || scope.scope.otherReason === '') { 
              e.cancel = true;
            } else {
              // Done!
            }
          },
          onclose: function () {
            return;
          }
        }).show();
      });

      scope.$on('$destroy', function() {
        element.unbind();
      });
    }
  };
}]);
Ayeye Brazo
  • 3,316
  • 7
  • 34
  • 67

1 Answers1

2

Whenever using add template with directives, $compile is necessary.

The compilation is a process of walking the DOM tree and matching DOM elements to directives.

angular.module('items').directive('cancelItem', ['$rootScope','$compile', 'Items', function ($rootScope,$compile, Items) {
  return {
    restrict: 'A',
    link: function (scope, element, attrs) {

      scope.reason = '';  // <--

      var item_id = attrs.cancelItem;
      element.bind('click', function (event) {
        event.stopPropagation();
        alertify.prompt(
          'Warning!',
          function (e, reason) {
            if (reason === '') { 
              e.cancel = true;
            } else {
              var data = {
                id: cancel_id,
                data: {
                  action: 'cancel'
                }
              };
              Items.update({ 
                id: item_id
              }, data)
              .$promise.then(function (data) {
                alertify.success('Item ' + item_id + ' has been cancelled');
                $rootScope.$broadcast('Item cancelled');
              });
            }
          },
          function () {
            return;
          }
        )
        .setContent(
          '<div id="alertify"><p>Are you sure you wish to CANCEL the item ' + item_id + '?</p>' +
          '<select class="ajs-input" ng-model="reason">' + 
          '<option ng-value="Reason 1">Option one</option>' + 
          '<option ng-value="Reason 2">Option two</option>' + 
          '<option ng-value="Reason 3">Option three</option>' + 
          '</select>' + 
          '<input class="ajs-input" type="text" ng-bind="reason"></div>'
        ); // <-- compile template
      });

      $compile(angular.element("#alertify").html())(scope);

      scope.$on('$destroy', function() {
        element.unbind();
      });
    }
  };
}]);
Yin Gang
  • 1,443
  • 1
  • 10
  • 15
  • Thanks for your answer. Actually, using your code, it doesn't show the select and a text input is visible with inside the code of my directive... – Ayeye Brazo May 18 '16 at 15:42
  • Thanks again, now it render correctly the HTML but it is not updating the `bind` yet... :( – Ayeye Brazo May 18 '16 at 16:08
  • Pretty sure `$compile` is the way out for your case, but I neither have any live demo nor feedback of errors, just have no idea how to correct my code. Or you can check [another question](http://stackoverflow.com/questions/37272009/create-mail-template-with-compile-in-angularjs), similar of yours. – Yin Gang May 19 '16 at 01:01
  • Solved using a different approach with Alertifyjs. Soon I will edit my post to include a complete solution. Your answer and help has been fundamental to let it work. Thanks. – Ayeye Brazo May 19 '16 at 13:09