0

I'm trying to create a custom module that is fairly similar to the modal provided in the ui.bootstrap library. I would like to be able to open and close it via a service, and pass some options. The problem, is, I'm somewhat new to angular, and I'm not entirely sure how this should be done.

I've read up on how to create a custom modules (this was a great post), And I understand that I'm going need a service in order to open it programatically, But after looking at the source code for I'm somewhat lost. I'm assuming I'll need to do the following:

  • Build a service to append an element to the body
  • That element should have a directive that will trigger... something or other?

But when I gave that a try, the directive didn't actually link up. For example:

angular.module("ui.sidePanel", [])
.service("$sidePanel", function($rootScope, $document){
  return{
    open: function(options){
        angular.element($document[0].body).append("<side-panel></side-panel>");
        console.log('Boop');
    }
  }
})
.directive("sidePanel", function(){
  return {
    restrict: "E",
    link: function(scope, element, attrs){
        console.log('Side Panel');
    }
  }
})

Would never log "Side Panel".

2
  • Couple of notes. First, it's bad practice to name your own stuff with a $ prefix - that is reserved for angular core stuff. Second, you most likely don't want to keep appending DOM nodes as you have it, intead write the DOM node controlled by a directive and ng-hide/ng-show based on state. Lastly, in your example, nothing calls $sidePanel.open() Commented Feb 25, 2014 at 20:48
  • @MattPileggi I suppose your right, I was just trying to go by ui.bootstrap's example. you're entirely right that I won't want to keep appending DOM nodes, but I was hoping for something a little more elegant then a ng-show/ng-hide since I would like to reuse this multiple places. Perhaps writing up a directive is the best way to go here. Commented Feb 26, 2014 at 13:33

1 Answer 1

0

Just appending html is not sufficient for your purposed, you would also need to compile the html (with $compile) in order for it to run the directive.

That being said I would suggest an alternative approach where the service does not manipulate dom, since that is not a best practice.

Your service can just hold the state of the modal, which your directive can watch and choose which content to show. I created a fiddle you can play with.

The service just holds a value for the modal to look at

myApp.factory('service', function () {
    return {    
        value: {
            data: ''
        }
    };
});

The directive scopes that value, so it knows when to show

link: function ($scope, $element, $attrs) {
    $scope.value = service.value;
}

Now whenever you set the value of the service, the directive can adjust accordingly

EDIT: some ui.bootstrap code

They seem to be using a service to fetch template urls and that pass it as content to the directive.

// In the $modal service
      function getTemplatePromise(options) {
        return options.template ? $q.when(options.template) :
          $http.get(options.templateUrl, {cache: $templateCache}).then(function (result) {
            return result.data;
          });
      }

If you are looking to dive in more you can check out their source

Hope this helps!

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

2 Comments

I remember being a little disgusted at myself for attaching elements to the DOM through the service, but I wasn't sure how else to do it without sticking the <side-panel> tag in my template. I should probably just suck it up and do it how you described, but I'm still curious to know how ui.bootstrap does it.
I added a little tidbit in my answer about ui.bootstrap.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.