0

I would like to know if I can simplify the modals of ui-bootstrap like the original ones in bootstrap, because for angular is a bunch of code I am really having a nightmare with the ui-bootstrap modals for angular. And it seems that the code is just for customize modals etc, but you need to add functions for open etc.

What if I need an other modal with other template? or what if I need many modals?

This is the code I have from the ui-bootstrap reference help. I tried to erease all unecesary code but still too complex.

VIEW

<div ng-controller="ModalDemoCtrl as $ctrl" class="modal-demo">
    <script type="text/ng-template" id="myModalContent.html">
        <div class="modal-header">
            <h3 class="modal-title" id="modal-title">I'm a modal!</h3>
        </div>
        <div class="modal-body" id="modal-body">
            <ul>
                <li ng-repeat="item in $ctrl.items">
                    <a href="#" ng-click="$event.preventDefault(); $ctrl.selected.item = item">{{ item }}</a>
                </li>
            </ul>
            Selected: <b>{{ $ctrl.selected.item }}</b>
        </div>
        <div class="modal-footer">
            <button class="btn btn-primary" type="button" ng-click="$ctrl.ok()">OK</button>
            <button class="btn btn-warning" type="button" ng-click="$ctrl.cancel()">Cancel</button>
        </div>
    </script>


    <button type="button" class="btn btn-default" ng-click="$ctrl.open('lg')">Large modal</button>
</div>

APP

// MODAL CONTROLLERS
myApp.controller('ModalDemoCtrl', function ($uibModal, $log, $document) {
    var $ctrl = this;
    $ctrl.items = ['item1', 'item2', 'item3'];

    $ctrl.animationsEnabled = true;

    $ctrl.open = function (size, parentSelector) {
        var parentElem = parentSelector ? 
        angular.element($document[0].querySelector('.modal-demo ' + parentSelector)) : undefined;
        var modalInstance = $uibModal.open({
            animation: $ctrl.animationsEnabled,
            ariaLabelledBy: 'modal-title',
            ariaDescribedBy: 'modal-body',
            templateUrl: 'myModalContent.html',
            controller: 'ModalInstanceCtrl',
            controllerAs: '$ctrl',
            size: size,
            appendTo: parentElem,
            resolve: {
                items: function () {
                    return $ctrl.items;
                }
            }
        });

        modalInstance.result.then(function (selectedItem) {
            $ctrl.selected = selectedItem;
        }, function () {
            $log.info('Modal dismissed at: ' + new Date());
        });
    };

    $ctrl.openComponentModal = function () {
        var modalInstance = $uibModal.open({
            animation: $ctrl.animationsEnabled,
            component: 'modalComponent',
            resolve: {
                items: function () {
                    return $ctrl.items;
                }
            }
        });

        modalInstance.result.then(function (selectedItem) {
            $ctrl.selected = selectedItem;
        }, function () {
            $log.info('modal-component dismissed at: ' + new Date());
        });
    };

    $ctrl.openMultipleModals = function () {
        $uibModal.open({
            animation: $ctrl.animationsEnabled,
            ariaLabelledBy: 'modal-title-bottom',
            ariaDescribedBy: 'modal-body-bottom',
            templateUrl: 'stackedModal.html',
            size: 'sm',
            controller: function($scope) {
                $scope.name = 'bottom';  
            }
        });

        $uibModal.open({
            animation: $ctrl.animationsEnabled,
            ariaLabelledBy: 'modal-title-top',
            ariaDescribedBy: 'modal-body-top',
            templateUrl: 'stackedModal.html',
            size: 'sm',
            controller: function($scope) {
                $scope.name = 'top';  
            }
        });
    };

    $ctrl.toggleAnimation = function () {
        $ctrl.animationsEnabled = !$ctrl.animationsEnabled;
    };
});

// Please note that $uibModalInstance represents a modal window (instance) dependency.
// It is not the same as the $uibModal service used above.

myApp.controller('ModalInstanceCtrl', function ($uibModalInstance, items) {
    var $ctrl = this;
    $ctrl.items = items;
    $ctrl.selected = {
        item: $ctrl.items[0]
    };

    $ctrl.ok = function () {
        $uibModalInstance.close($ctrl.selected.item);
    };

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

// Please note that the close and dismiss bindings are from $uibModalInstance.

myApp.component('modalComponent', {
    templateUrl: 'myModalContent.html',
    bindings: {
        resolve: '<',
        close: '&',
        dismiss: '&'
    },
    controller: function () {
        var $ctrl = this;

        $ctrl.$onInit = function () {
            $ctrl.items = $ctrl.resolve.items;
            $ctrl.selected = {
                item: $ctrl.items[0]
            };
        };

        $ctrl.ok = function () {
            $ctrl.close({$value: $ctrl.selected.item});
        };

        $ctrl.cancel = function () {
            $ctrl.dismiss({$value: 'cancel'});
        };
    }
});

As you can see, is bunch of code. The only think I want is to have the option of the old fashion way, like:

My button with the modal ID

My modal with the content

Apparently this is impossible with ui-bootstrap, any help will be apreciated

3
  • If you have numerous different modals in the app creating a service that wraps all the $uibModal.open() code can cut down on a lot of code duplication Commented Apr 7, 2017 at 1:21
  • As I understand you want a modal which is open according to ID and content associated with that ID right? Commented Apr 7, 2017 at 5:45
  • Thing is, I implemented, and it works, but just for one modal template, I can have only one content arrangement there, I didn't understand well, but can have different design with this? Or need to copy the whole code in my app for and other modal? Other thing I notice is that I can not use the modal outside the controller. I already have a controller called homeController and inside I have de controller for this modal. For me is a total mess compared to the original bootstrap way. Commented Apr 8, 2017 at 14:56

1 Answer 1

1

I have to agree with you on this one, I found the documentation to be a bit verbose for me. As you can see, my templateURL is referencing a separate .html file in the same directory that contains the modal content.

Here's what my solution looks like:

In my controller:

myApp.controller('ModalController', function ($log, $uibModal, $scope) {
  $log.debug('ModalController');

  this.createModal = function() {
    let modal = $uibModal.open({
      backdrop: 'static',
      keyboard: true,
      backdropClick: false,
      template: require('./modal-content.html'),
      scope: $scope
    });

    $scope.modalInstance = modal;
    return modal.result;
  };

  this.triggerModal = function() {
    this.createModal()
    .then( (data) => {
      this.handleSuccess(data);
    })
    .then(null, (reason) => {
      this.handleDismiss(reason);
    });
  };

  this.yes = function() {
    $scope.modalInstance.close('Yes Button Clicked');
  };

  this.no = function() {
    $scope.modalInstance.dismiss('No Button Clicked');
  };

  this.handleSuccess = function(data) {
    $log.info('Modal closed: ' + data);
  };

  this.handleDismiss = function(reason) {
    $log.info('Modal dismissed: ' + reason);
  };
}

Here's what the content of 'modal-content.html' looks like:

<div class="modal-header">
  <h3 class="modal-title">I'm a modal!</h3>
</div>
<div class="modal-body">
  <ul>
    <li>item 1</li>
    <li>item 2</li>
    <li>item 3</li>
  </ul>
</div>
<div class="modal-footer">
  <button class="btn btn-primary" ng-click="landingModalCtrl.yes()">yes</button>
  <button class="btn btn-warning" ng-click="landingModalCtrl.no()">no</button>
</div>

Hope that helps!

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you!, I will try this solution. And you are right, I don't know to much about documentations, but ui boostrap documentations is hard to follow, especially for people from a design background
Yah no problem, I hope that helps. My implementation of Angular is slightly different than the syntax we're using here (I'm actually using a componentized structure in my app) but I modified it to resemble the example from the ui-bootstrap docs. Let me know if I can help you further.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.