How to build a global Ionic modal that can be showed with specific options?

I'd like to build a global modal for issue reporting within my Ionic App. In several pages of my app, I have a "Report Issue" button that should open a modal containing a form.

The modal is exactly the same for each page (form with issue description), however I'd like to pass sometimes additional data to it. IE:

  • I'm on the "itemA" view, I click the "Report Issue" button, I'd like to attach "itemA.id" to the issue.
  • I'm on the main page, I click the "Report Issue", it only sends the issue description.

Requirements:

  • I'm using $ionicModal
  • I'd like not to pollute the $rootScope.
  • I'd like to avoid code duplication as much as possible (not defining the modal behavior in every controller..)
  • I'd like not to store these additional issue data into a global var.
  • I'd like to display another "success modal" when the form submission is successful.

Ideally, the only code in each controller should be

.controller('Ctrl', function($scope, $issueModal){
    $scope.reportIssue = function(){
        $issueModal.show({item_id: 42});
    }
});

I tried this implementation but I'm not satisfied for these reasons:

  • It does not handle "$destroy" events from the parent view.
  • I create a new modal everytime I call ".show()", thereby I need to destroy the modal whenever it's closed or "hidden".

I'd be thankful to anyone giving me directions!

What you're describing can be accomplished by using angulars $provide service to decorate the ionModalDirective.

Here is an example using the ionActionSheetDirective to override the template, but if you didn't want to override the template then that'd be fine too, you could just override the link function based on the arguments that get passed in. It is really up to you. The key here is that the resulting template, link function, etc will be provided to angular whenever you use the ionModal in your app.:

angular.module('ionic').config(['$provide', function ($provide) {
  $provide.decorator('ionActionSheetDirective', ['$delegate', function ($delegate) {
    var directive = $delegate[0];

    // Here we are completely overriding the template definition for the ionActionSheetDirective
    directive.template = '' +
      '<div class="action-sheet-backdrop action-sheet-backdrop-fisdap">' +
      '<div class="action-sheet-wrapper">' +
      '<div class="action-sheet">' +
      '<div class="action-sheet-group action-sheet-group-title" ng-if="titleText">' +
      '<div class="action-sheet-title" ng-bind-html="titleText"></div>' +
      '</div>' +
      '<div class="action-sheet-group action-sheet-group-buttons">' +
      '<button class="button button-outline" ng-click="buttonClicked($index)" ng-repeat="button in buttons" ng-class="button.classes" ng-bind-html="button.text"></button>' +
      '<button class="button button-outline button-assertive destructive" ng-click="destructiveButtonClicked()" ng-bind-html="destructiveText" ng-if="destructiveText"></button>' +
      '<button class="button button-outline button-balanced" ng-click="cancel()" ng-bind-html="cancelText" ng-if="cancelText"></button>' +
      '</div>' +
      '</div>' +
      '</div>' +
      '</div>';

    // Store the old compile function
    var compile = directive.compile;

    // Overwrite the old compile function
    directive.compile = function () {

      // Get the link function from the old directive
      var link = compile.apply(this, arguments);

      // If we wanted to add some elements programatically we'd do it here
      // tElement.append('<div>Added in the decorator</div>');

      // Use the link function from the old directive for this directive
      return function () {
        link.apply(this, arguments);

        // We can extend the link function here if we wanted to
      };
    };

    return $delegate;

  }]);
}]);