Bootstrap alert message represented as modal, angular

28,845

Solution 1

I'll answer on my own question.

Simple way

The flow is pretty simple and straightforward. We don't reinvent the wheel here.

We don't need nor header neither footer:

Dialog template HTML:

<div class="modal-body" style="padding:0px">
    <div class="alert alert-{{data.mode}}" style="margin-bottom:0px">
        <button type="button" class="close" data-ng-click="close()" >
            <span class="glyphicon glyphicon-remove-circle"></span>
        </button>
        <strong>{{data.boldTextTitle}}</strong> {{data.textAlert}}
    </div>
</div>

We even don't need to use ng-class:

class="alert-{{data.mode}}"

where mode might be: success, info, warning, danger


Modal Instance Controller:

var ModalInstanceCtrl = function ($scope, $modalInstance, data) {
  $scope.data = data;
  $scope.close = function(/*result*/){
    $modalInstance.close($scope.data);
  };
};

And this is modal configuration and content:

 $scope.data = {
    boldTextTitle: "Done",
    textAlert : "Some content",
    mode : 'info'
  }  

var modalInstance = $modal.open({
      templateUrl: 'myModalContent.html',
      controller: ModalInstanceCtrl,
      backdrop: true,
      keyboard: true,
      backdropClick: true,
      size: 'lg',
      resolve: {
        data: function () {
          return $scope.data;
        }
      }
    });

Demo Plunker


enter image description here

Directive way

Demo 2 Plunker

We can put all above written code into directive for better maintenance:

HTML

<button class="btn btn-success" ng-click="open()" >success
          <my-alert
          bold-text-title="Done"
          text-alert="Some content"
          mode="success"
          ></my-alert>
</button>

Directive

.directive('myAlert', function($modal,$log) {
      return {
        restrict: 'E',
        scope: {
          mode: '@',
          boldTextTitle: '@',
          textAlert : '@'
        },
        link: function(scope, elm, attrs) {
        
       scope.data= {
                mode:scope.mode,
                boldTextTitle:scope.boldTextTitle,
                textAlert:scope.textAlert
              }
        
       var ModalInstanceCtrl = function ($scope, $modalInstance, data) {
          
           console.log(data);
          
           scope.data= {
              mode:scope.mode || 'info',
              boldTextTitle:scope.boldTextTitle || 'title',
              textAlert:scope.textAlert || 'text'
          }
        };
        
        elm.parent().bind("click", function(e){
           scope.open();
       });
        
     scope.open = function () {
        
        var modalInstance = $modal.open({
          templateUrl: 'myModalContent.html',
          controller: ModalInstanceCtrl,
          backdrop: true,
          keyboard: true,
          backdropClick: true,
          size: 'lg',
          resolve: {
            data: function () {
              return scope.data;
            }
          }
        });
    
    
        modalInstance.result.then(function (selectedItem) {
          scope.selected = selectedItem;
        }, function () {
          $log.info('Modal dismissed at: ' + new Date());
        });
    }
  }
  };
})

Hope it will save time to someone.

Solution 2

I've made a service and controller which depends of eachother:

.service('AlertService', function($uibModal){
    /*
        headerText - presents text in header
        bodyText - presents text in body
        buttonText - presents text in button. On its click if method parameters is not passed, modal will be closed.
                    In situation that the method parameters is passed, on its click, method will be called. For situations
                    like that, there is parameter buttonText2 which will be used as cancel modal functionality.
        method - presents passed function which will be called on confirmation
        buttonText2 - presents text in button for cancel

     */
    var alert = function(headerText, bodyText, buttonText, method, buttonText2){

        method = method || function(){};
        buttonText2 = buttonText2 || '';

        $uibModal.open({
            animation: true,
            templateUrl: '/static/angular_templates/alert-modal.html',
            controller: 'AlertModalInstanceCtrl',
            size: 'md',
            resolve: {
                headerText: function () {
                  return headerText;
                },
                bodyText: function () {
                  return bodyText;
                },
                buttonText: function () {
                  return buttonText;
                },
                method: function () {
                    return method;
                },
                buttonText2: function () {
                    return buttonText2;
                }
            }
        });
    };

    return{
        alert: alert
    };

})
.controller('AlertModalInstanceCtrl', function ($scope, $uibModalInstance, headerText, bodyText, buttonText, method, buttonText2) {
    $scope.headerText = headerText;
    $scope.bodyText = bodyText;
    $scope.buttonText = buttonText;
    $scope.method = method;
    $scope.buttonText2 = buttonText2;

    $scope.ok = function () {
        $scope.method();
        $uibModalInstance.dismiss('cancel');
    };

    $scope.cancel = function () {
        $uibModalInstance.dismiss('cancel');
    };
});

and html file:

<!--Modal used for alerts in AlertService-->

<div class="modal-header">
    <h3 class="modal-title">{[{ headerText }]}</h3>
</div>
<div class="modal-body">
    <p>{[{ bodyText }]}</p>
</div>
<div class="modal-footer">
    <button class="btn btn-default" ng-click="cancel()" ng-if="buttonText2">{[{ buttonText2 }]}</button>
    <button class="btn btn-primary" ng-click="ok()">{[{ buttonText }]}</button>
</div>

Now, depending for what type you want to use it, you have a few options: -If you pass headerText, bodyText and buttonText, it will behave like a classic alert modal

AlertService.alert('Some header', 'Some message', 'Text button');

-If you pass headerText, bodyText, buttonText and method, it will behave like a classic alert modal but with the function which you can pass and later handle in the controller

AlertService.alert('Are you sure?', 'Are you sure you want to create this round', 'Ok', $scope.createRound);

$scope.createRound = function(){
//do something
}

-And the last one. If you pass all the parameters, it will act like the previous one, just with the possibility to cancel and close modal.

AlertService.alert('Are you sure?', 'Are you sure you want to create this round', 'Ok', $scope.createRound, 'Cancel');

$scope.createRound = function(){
//do something
}

Of course, if you want to use this, you'll have to inject angular ui bootstrap. I wasted a lot of time to develop this, but it worth. It was annoying to create every time a new controller, new template and all the other things.

From the controller then you can easily use it, just inject it first.

Share:
28,845
Maxim Shoustin
Author by

Maxim Shoustin

Enthusiastic full-stack developer with a passion for science, architect and team leader. Strong proponent of open licensing. Love helping people Work at AppsFlyer

Updated on July 09, 2022

Comments

  • Maxim Shoustin
    Maxim Shoustin almost 2 years

    Bootstrap 3 provides Bootstrap: event messages: success, info, warning, danger.

    However sometimes the view doesn't have enough space to show up the event message.

    Is there easy way to wrap event with modal in Angular?

    This is a template I started to play with

  • harishr
    harishr over 9 years
    thanks for it. requesting you to add 2 features: 1) option to make it non blocking, with no fading effect 2) auto close after sometime..
  • harishr
    harishr over 9 years
    it would be great if you can submit it as a modules on ngmodules.com
  • Anton Dozortsev
    Anton Dozortsev over 8 years
    @MaximShoustin Nice alert but how I can open it in JS code just invoking function for example ... myAlert(); ... ? In other words show alert without HTML button
  • Maxim Shoustin
    Maxim Shoustin over 8 years
    @AntonDozortsev not at all, the modal lays under directive so you can easily grab modal code and call it without directive
  • Anton Dozortsev
    Anton Dozortsev over 8 years
    @MaximShoustin But that is a problem I don't want copy mode code all time
  • Maxim Shoustin
    Maxim Shoustin over 8 years
    @AntonDozortsev so create somewhere this directive once , add watcher and call some parameter in directive that should trigger watcher and show up the modal
  • Anton Dozortsev
    Anton Dozortsev over 8 years
    @MaximShoustin OK. I will try you suggestions. Thanks for all.