4

I'm creating a directive that shows a modal when user click on a button:

The directive template:

<button ng-click="showModal()">Show Modal</button>

Directive usage:

<modal-btn>
  <div id="modal-content">
    <p>This is the modal content that I want to render in the Modal {{someModel}}</p>
  </div>
</modal-btn>

So before I compile the directive, I need to grap the content, show the button, and when the user clicks on the button I show the modal containing the <div id="modal-content">....

How to get directive inner content before compiling it and replacing it by the template

Sn0opr
  • 1,016
  • 2
  • 12
  • 38
  • This is quite broad. Where are you rendering the modal content? It's not likely under ``, right? What scope is exposed to the modal, e.g. `someModel`? You need to break the problem into smaller question, in my opinion. If you need a starter, take a look at how [`$modal`](https://angular-ui.github.io/bootstrap/#/modal) is implemented by [angular.ui](https://github.com/angular-ui/bootstrap/tree/master/src/modal) – New Dev May 17 '15 at 16:40

1 Answers1

4

Hm.. it's actually quite interesting pattern for using modal with local content like this.

So, to accomplish that all you need is transclude option of angular directive. There is a good article about transclude.

HTML

<modal-btn>
  <div class="modal-content">
    Lorem Ipsum Dolor Sit Amet `{{currentScopeData}}`
  </div>
</modal-btn>

We create the modal btn directive and modal content inside it. Take a look at expression - at this point we can actually use the currentScopeData from our current scope (Controller of the page or whatever).

Directive Template

<button ng-click="showModal()">Show Modal</button>

Just a button with ng-click like yours.

Directive

App.directive('modalBtn', ['Config', function (Config) {

    function link(scope, element, attrs, ctrl, transclude) {

        // Get your modal holder element which may be located anywhere in your application
        var modalHolder = angular.element(document.querySelector('#modal-holder'));

        /**
         * Get transcluded content (which is located inside <modal-btn></modal-btn>)
         *     and set it into scope
         */
        transclude(scope, function(clone, scope) {
            scope.modalContent = clone;
        });

        /**
         * On button click set our transcluded content to the modal holder area 
         */
        scope.showModal = function () {
            modalHolder.empty().append(scope.modalContent);
        }
    }

    return {
        templateUrl: Config.rootPath + 'shared/modal/modal-btn-view.html',
        link: link,
        replace: true,
        // Set transclude option
        transclude: true
    };
}]);

All actions are commented. Generally we get our inner content from transcluded function provided inside directive and set it to the scope. And when user clicks on the button showModal fired and insert our content in some modal holder, which may be anywhere in your html file.

After content is inserted you need to provide some modal showing functional (maybe add class on the modalHolder or something like that it's up to you).

Alex Sidorenko
  • 546
  • 1
  • 3
  • 14
  • Thank you for your brief reply, this is awesome!, but, when I console.log ```clone``` I get an array that contains [0:text, 1:div, 0:text], I can get the content by doing clone[1] but why this is returning an array, Thank you one more time. – Sn0opr May 17 '15 at 21:27
  • 1
    Hi, you are welcome. About clone - you have [0:text, 1:div, 0:text], because trancscluded data contains line breaks. So there is line-break, div , line break. But this array is actual angular.element so you can append it like this with linebreaks. I don't now how to trim it safetely to be honest, will investigate this when have time. – Alex Sidorenko May 18 '15 at 05:05