Ayeye Brazo Ayeye Brazo - 6 months ago 40
AngularJS Question

Angular directives not working in alertify setContent content

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();
});
}
};
}]);

Answer

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();
      });
    }
  };
}]);
Comments