How to transclude content in ui bootstrap modal directive

11,154

Solution 1

OP, your snippet is exactly what I was looking to do—thanks!

I managed to get your plunk working by passing replace:true as well as transclude: true

Here's the updated plunk http://plnkr.co/edit/gxCS2V?p=preview

I'm new to Angular, so I was interested to know why:

replace - if set to true then the template will replace the current element, rather than append the template to the element.

(via the Angular docs)

Which, of course makes sense once you know.

Good to know if you want to make your directive especially recyclable. Modals are pretty perfect example.

Related : ui-bootstrap is worth checking out.

Solution 2

Check this solution, you dont need a extra controller or angular-ui for that only pass a simple handler and use it

example.js

angular.module('plunker', [], function() {

})

.directive('modal', function() {
  return {
    restrict : 'E',
    templateUrl: 'myTpl.html',
    transclude: true,
    controller: function($scope) {
      // you need get a better unique generator
      $scope.modal_id = 'modal_' + Math.floor((Math.random()*100+1));
      $scope.handler = $scope.modal_id;
    },
    scope : {
      handler : '='
    }
  };
})
.run();

index.html

<!doctype html>
<html ng-app="plunker">
  <head>    
    <link href="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet">    
  </head>
<body>

<div ng-init="handler = null">  
  <modal handler="handler">
    <h1>Content</h1>
  </modal>  
  <a href="#{{handler}}" role="button" class="btn primary" data-toggle="modal">Open me</a>
</div>
    <script src="//ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
    <script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.5/angular.js"></script>    
    <script src="//netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
    <script src="example.js"></script>
</body>
</html>

myTpl.html

<div id="{{modal_id}}" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="{{modal_id}}Label" aria-hidden="true">
    <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button>
        <h4 id="{{modal_id}}Label">I'm a modal!</h4>
    </div>
    <div class="modal-body">
      <div ng-transclude></div>
    </div>    
    <div class="modal-footer">
      <button class="btn" data-dismiss="modal" aria-hidden="true">Cancel</button>
    </div>
</div>

look how works in plunker

Share:
11,154
Florian F
Author by

Florian F

Work @Kap_IT

Updated on July 25, 2022

Comments

  • Florian F
    Florian F almost 2 years

    I've made a custom directive on top of ui bootstrap modal directive so I can use the same modal template everywhere in my app.

    My directive works until I try to transclude its content into the template:

    http://plnkr.co/edit/YPESA3?p=preview


    From index.html

    <div ng-controller="ModalDemoCtrl">
      <button class="btn" ng-click="open()">Open me!</button>
      
      <my:modal open="shouldBeOpen" close="close()">
        <h1>Content</h1>
      </my:modal>
    </div>
    

    Module code:

    angular.module('plunker', ['ui.bootstrap'])
    
    .controller('ModalDemoCtrl', function($scope) {
      $scope.open = function () {
        $scope.shouldBeOpen = true;
      };
    
      $scope.close = function () {
        $scope.closeMsg = 'I was closed at: ' + new Date();
        $scope.shouldBeOpen = false;
      };
    
      $scope.items = ['item1', 'item2'];
    
    })
    
    
    .directive('myModal', function() {
      return {
        restrict : 'E',
        templateUrl: 'myTpl.html',
        //transclude: true,
        scope : {
          open : '=',
          close : '&'
        }
      };
    });
    

    Modal template:

    <div modal="open">
        <div class="modal-header">
            <h4>I'm a modal!</h4>
        </div>
        <div class="modal-body">
          <!--<div ng-transclude/>-->
        </div>
           
        
        <div class="modal-footer">
          <button class="btn btn-warning cancel" ng-click="close()">Cancel</button>
        </div>
    </div>
    

    Uncomment transclude property from the directive and the template and you'll see you get a TypeError: undefined is not a function.

    I can't figure what I'm doing wrong.

  • Florian F
    Florian F over 11 years
    Thanks for your answer. I'll have a try. However, to be honest, , I'm more intersted to know what is wrong in my example
  • rkmax
    rkmax over 11 years
    I decided to make a solution that does not use angular-ui by a bad experience because angular-ui gave me more problems than solutions. but will watch closely the modal directive from angular-ui