replace and transclude in Angular directives

I’m still learning about Angular JS at the moment, but since I haven’t written a post this month about anything I have learned, I thought I’d log this one down (I should’ve written it earlier since I worked through this a few weeks ago), which was something I figured out at work.

I’ve only had a little bit of exposure to Angular before, so I’m only learning little fragments as I grasp a greater understanding of the bigger picture.

This problem involved pulling out some markup into a new directive. I’m not yet familiar with the usage of controllers and directives and in exactly what situation they should be created, so this post won’t cover that.

The code for the directive

This is roughly the code I used for the directive; your projects may vary. I’ve marked out important things that I will be outlining.

define([
  'config',
  'vendor/angular',
  'modules/emailbuilder/module,
  'vendor/text!modules/emailbuilder/templates/sidebarSettings.html'

],

function (config, angular, module, template) {
  function SidebarSettings($rootScope) {
    return {
      restrict: 'E',
      replace: true,
      template: template,
      link: function (scope, element, attrs) {

      }
    };
  }

  module.directive('sidebarSettings', ['$rootScope', SidebarSettings]);

});

Attributes versus elements

There are a couple of ways to use directives.

This is an example of using an attribute, where you would use restrict: 'A' in the directive. The documentation states that you should an attribute when you are decorating an existing element with new functionality.

<div sidebar-settings></div>

I previously used a directive as an attribute when I wanted to update the keyboard detection on the webpage.

You should use an element (that is, restrict: 'E') when you are creating a component that is in control of the template.

<sidebar-settings></sidebar-settings>

This was used quite frequently throughout our app, to do similar things to what I needed to do, so I went for this option.

You can also use restrict: 'EA', so that you can use the directive as either an attribute or element. There are also some other options.

Code in the directive is written in camelCase and when written in markup should be converted to lowercase with hyphens as separators, for example camel-case.

The template

I created a new file for this template (you can see the file path specified above), although you can put the template content inside the directive file too. It depends how you would like to do it, but it makes sense to create a new file when you have more content.

To test, I simply put this in the template file:

<h1>settings</h1>

I realised that this did not work so I learned that you have to wrap it all in a div or some other kind of wrapping element! 😉

<div>
  <h1>settings</h1>
</div>

If you wanted to put the template content in the directive you would write this:

template: '<div><h1>settings</h1></div>'

Replacing content

Normally, the appearance of elements in the DOM would be like this:

<sidebar-settings>
  <div>
    <h1>settings</h1>
  </div>
</sidebar-settings>

However, this may not be exactly what I want. Depending on what is in the template, this could make a mess and not be very neat. This is where replace: true comes in. By using this, the appearance of my content in the DOM would be as follows:

<div>
  <h1>settings</h1>
</div>

Transclusion

Transclusion is another interesting thing that seems to work similarly to replace, but concerns markup written inside the <sidebar-settings>. I don’t quite have my head around this, but adding transclude: true to the options allows the content in here to be displayed.

Let’s say you have this:

<sidebar-settings>
  <img src="cog.svg" alt="settings icon">
</sidebar-settings>

You might have some other stuff in there, but for whatever reason, you want this content to be here rather than in the template, but you also want the template to have content that is displayed.

You would write your directive a little like this (this example is using the template inside the directive:

    return {
      restrict: 'E',
      replace: true,
      transclude: true,
      template: '<div><h1>settings</h1><div ng-transclude></div>',
      link: function (scope, element, attrs) {

      }
    };

This means that the DOM content will be displayed like this:

<div>
  <h1>settings</h1>
  <div>
    <img src="cog.svg" alt="settings icon">
  </div>
</div>

The <div ng-transclude> is replaced with the original content of the element to which the directive is being applied. Again, as I mentioned, I’m not fully aware of the use cases for this. I’ve known that I had to use it a couple of times to get existing code to work, though.

That’s it for my learnings about Angular so far. 🙂 Looking forward to any feedback or anything more anyone can teach me!

Disclaimer: Code samples may not reflect the code that I used. Some modifications were made due to confidentiality and to better explain the steps of this task.

Leave a Comment

Comments on this post

Not me, Georgie, as I’m just getting started with a Coursera course on Angular JS tomorrow (I think, I have to recheck the start date). But it looks like a pretty framework to use for web apps.

P.S. I had given up learning how to program in a number of language, but the passion and confidence are coming back and I’m going to try and up my PHP competencies, too.

I’ve been hearing about Angular JS for a while but never really took the time to know a bit about it (until now – gotta learn the backstory before reading the post (; ).

Seeing constructors definitely takes this to the really back end of web dev… Or at least it’s called directives in this case :’). I can see how everything works together (or gets aligned in this case). Sounds like this is the type of code for some kind of automation. Though, I am looking forward to an end product from AngularJS out of you 😉.

Now, this is making me wonder what some web apps are made from…

I started teaching myself AngularJS recently as well, and it sounds like we’re learning it about the same way! I’m slowly beginning to grasp it piece by piece.

Your explanations of elements vs attributes in directives, and the replace and transclude functionality are really helpful! I hope you’ll post more about Angular in the future. 🙂

Ooo, thanks for sharing this Georgie! I’m terrible at Javascript but I’ve been reading up on it recently ready for my CF:G class next week (Week 6: Javascript, jQuery!) and came across AngularJS. It may be something I’ll really get into in the future! 😄