Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

AngularJS: How to create a directive that adds/removes itself from DOM when needed?

If i have a custom modal directive that looks something like this:

return {
  restirct: 'E',
  templateUrl: 'modal.html',
  scope: {
    modalContent: "=",
    modalOpen: "="
  }
}

and the html:

<ng-modal modal-content="content" modal-open"active"></ng-modal>

how can i make sure that the modal doesn't exist in the DOM when it's closed and once open it inserts itself into the DOM? I have to insert the directive into the html or else the directive won't work but that means that when i run the application the modal already exists in the html even if it wasn't opened.

I created a plunker of what i have so far here but it only hides/shows the modal using css classes instead of removing it completely

EDIT:

I created another version here which actually adds/removes the directive from the DOM. It's based on this article but it requires splitting the logic for adding/removing the directive between the directive and an external controller (The external controller handles adding the element and the directive handles the removing). I want the directive to handle everything, is this possible?

like image 479
Ahmed Wagdi Avatar asked Nov 08 '22 18:11

Ahmed Wagdi


1 Answers

Does this do what you want? I wrapped the contents of your template with a single div so that it was easier to grab the whole chunk in one variable. Then I add and remove that div depending on whether you want to show or hide it.

I do not believe that you can remove the <ng-modal> element, but this at least removes everything inside of it...

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

html

<div>
  <div class="modal hide">
    <h4>{{modalContent.title}}</h4>
    <p>{{modalContent.text}}</p>
    <button ng-click="close()">Close Modal</button>
  </div>

  <div class="modal-overlay"></div>
</div>

js

var ModalDirective = function() {
  return {
    restirct: 'E',
    templateUrl: 'modal.html',
    scope: {
      modalContent: "=",
      modalOpen: "="
    },
    link: function(scope, element, attrs) {
      var modalElements = element.children()[0];
      console.log(element);

      function addModal() {
        console.log('Opening modal');
        element.addClass('open');
        //add the modal elements back into the directive
        if (modalElements) {
          //should be 0
          console.log('Element child count before add', element.children().length);
          element[0].appendChild(modalElements);
           //should be 1
           console.log('Element child count after add', element.children().length);
        }
      }

      function removeModal() {
        element.removeClass('open');
        console.log('Closing modal');
        if (modalElements) {
          //remove the modal elements from the directive
           //should be 1
          console.log('Element child count before remove', element.children().length);
          element[0].removeChild(modalElements);
          //should be 0
          console.log('Element child count after remove', element.children().length);
        }
      }

      scope.$watch('modalOpen', function(newVal, oldVal) {

        if (newVal) {
          addModal();
        } else {
          removeModal();
        }

      });

      scope.close = function() {
        scope.modalOpen = false;
      }
    }
  }
}
like image 96
TwitchBronBron Avatar answered Nov 14 '22 22:11

TwitchBronBron