The Fabio
The Fabio

Reputation: 6250

How to inject AngularJS custom directives into a bootstrap pre-loaded modal?

I am new to angular.js and after watching the codeschool free course I decided to try something different with it.

I was trying to use a button to:

  1. inject an Angular custom directive into an already existing bootstrap modal body;
  2. push a JSON array from an Angular controller into this directive;
  3. display the bootstrap modal

I created the following files for this test:

** pictures-table.html:

<p ng-hide="pictures.length">No Pictures</p>
<table ng-show="pictures.length">
  <thead>
  <tr>
    <th>Picture</th>
    <th>Label</th>
    <th>Remove</th>
  </tr>
  </thead>
  <tbody>
  <tr ng-repeat="aPic in pictures">
    <td><img ng-src="{{aPic.pThumb}}"/></td>
    <td><input type='text' ng-model='aPic.text'/></td>
    <td><button class="close" type="button"><span>&times;</span></button></td>
  </tr>
  </tbody>
</table>

** loadNg.js:

(function () {
    var app = angular.module('ngMod', []);    
    app.controller("ItemsController", function () {
        var theControler = this;
        theControler.item = {id:1, name:"aaaa", pictures: [
          {text:"pic 1", pLarge:"1.jpg", pThumb:"1s.jpg"},
          {text:"pic 2", pLarge:"2.jpg", pThumb:"2s.jpg"},
          {text:"pic 3", pLarge:"3.jpg", pThumb:"3s.jpg"},
          {text:"pic 4", pLarge:"4.jpg", pThumb:"4s.jpg"}
          ]};

        theControler.editPictures = function () {
            $('.modal-title').html('Edit Pictures');
            $('.modal-body').html('<pictures-table></pictures-table>');
            $('#btnLaunchModal').click();
        };

    });
    app.directive('picturesTable', function () {
        return {
            restrict: 'E',
            templateUrl: 'pictures-table.html'
        };
    });

})();

I placed the standard boostrap modal on the botton of my "index.html" file, and added a hidden button to trigger it (yeah, I just copied it from existing code):

<!DOCTYPE html>
<html ng-app="ngMod">
<head>
  <title>testNG</title>
  <link href="bootstrap.css" media="all" rel="stylesheet">
  <link href="bootstrap-theme.css" media="all" rel="stylesheet">
</head>
<body role="document">


<div class="container theme-showcase" role="main" ng-controller="ItemsController as itemsCTRL">
    <p><strong>{{itemsCTRL.item.id}} -- {{itemsCTRL.item.name}}</strong></p>
    <button class="btn btn-lg btn-default" type="button" ng-click="itemsCTRL.editPictures()">Call Modal</button>
    <pictures-table></pictures-table>
</div>

<button id="btnLaunchModal" type="button" style="display: none" data-toggle="modal" data-target="#theModal">
  Launch modal
</button>
<div class="modal fade" id="theModal">
  <div class="modal-dialog">
    <div class="modal-content">
      <div class="modal-header">
        <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">&times;</span></button>
        <h4 class="modal-title"></h4>
      </div>
      <div class="modal-body"></div>
      <div class="modal-footer">
        <button type="button" class="btn btn-default" data-dismiss="modal">Cancel</button>
        <button type="button" class="btn btn-primary">Save changes</button>
      </div>
    </div>
  </div>
</div>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js"></script>
<script src="bootstrap.js"></script>
<script src="angular.js"></script>
<script src="loadNg.js"></script>
</body>
</html>

test 01: use the directive "picturesTable" into index file "index.html" (this part works fine):

Now the problem:

I tried to inject the custom directive with the controller function "editPictures". I linked this function to a button on the index page.

When clicking the button "Call Modal" the bootstrap modal is displayed, but the generated html for the "modal-body" part did not evaluate my injected directive. I did not attempted to set the JSON object yet. The injected html looks like this:

...
<div class="modal-body">
    <pictures-table></pictures-table>
</div>
...

I was expecting angular directive's magic to take place, what would I be missing?

Should I just ignore this test and explore other ways to inject the directive into this modal? If so what would be a better approach?

Any help is appreciated.

Upvotes: 0

Views: 1287

Answers (1)

Tjaart van der Walt
Tjaart van der Walt

Reputation: 5179

You need to compile your directive html via the $complile service provided by angular and add the compiled element (not the plain html) to the modal. Try the following snippet:

$compile('<pictures-table></pictures-table>')(scope, function(clonedElement, scope) {
    $('.modal-body').html(clonedElement);
});

You will have to update your controller declaration by injecting the $compile service

app.controller("ItemsController", ['$compile', function ($compile) {

}]);

Your code should look something like this:

app.controller("ItemsController", ['$compile','$scope', function ($compile,$scope) {
 var theControler = this;
    theControler.item = {id:1, name:"aaaa", pictures: [
      {text:"pic 1", pLarge:"1.jpg", pThumb:"1s.jpg"},
      {text:"pic 2", pLarge:"2.jpg", pThumb:"2s.jpg"},
      {text:"pic 3", pLarge:"3.jpg", pThumb:"3s.jpg"},
      {text:"pic 4", pLarge:"4.jpg", pThumb:"4s.jpg"}
      ]};
    $scope.pictures = theControler.item.pictures;
    theControler.editPictures = function () {
        $('.modal-title').html('Edit Pictures');
        $compile('<pictures-table></pictures-table>')($scope,   function(clonedElement, $scope) {
           $('.modal-body').html(clonedElement);
        });
        $('#btnLaunchModal').click();
    };
}]);

Upvotes: 1

Related Questions