1

I am using directives to try to replace some of the often-reoccurring template code that i must write with something simpler.

lets say I have the following original markup:

<!-- section with repeating stuff in it -->
<div some-attributes etc="etc" very-long-tag="true">
    <p class="lead">Some description text</p>

    <div class="row section short" ng-repeat="row in things">
      <div class="col-sm-6 col-md-4" ng-repeat="app in row.col">
        <div class="thumbnail">
          <img ng-src="im/things/{{app.image}}" alt="..." class="img-circle" width="250">
          <div class="caption">
            <h3>{{app.name}}</h3>
            <p>{{app.desc}}</p>
          </div>
        </div>
      </div>
    </div>
</div>

and I want to simplify it by doing something like this:

<!-- section with repeating stuff in it -->
<xx title="Some description text">
    <!-- this innerHTML gets passed to the directive -->
    <div class="row section short" ng-repeat="row in things">
      <div class="col-sm-6 col-md-4" ng-repeat="app in row.col">
        <div class="thumbnail">
          <img ng-src="im/things/{{app.image}}" alt="..." class="img-circle" width="250">
          <div class="caption">
            <h3>{{app.name}}</h3>
            <p>{{app.desc}}</p>
          </div>
        </div>
      </div>
    </div>
    <!-- end of innerHTML -->
</xx>

...where there are a several attributes that can be used to shorten the overall block, the directive is currently written this way:

_d.directive('xx', function() {
  return {
    scope: {
      'color': '=',
      'option': '=',
      'title': '=',
      'image': '=',
      'image-pos': '=',
      'image-size': '='
    },
    restrict: 'E',
    transclude: false,
    template: function(element, scope) {
      var inside = 'x';
      var content = element[0].innerHTML;
      var title = scope.title;
      var color = scope.color ? 'style="background-color: '+scope.color+'"' : "";
      var title = scope.title ? '<h2 class="centertext marginBottom20">'+scope.title+'</h2>' : '';
      return ['<div class="section row short" '+color+' ng-transclude>',
        title,
        content, //this may contain {{template code}}, but it always gets omitted
        '</div>'
      ].join("\n");
    },
  };
});

The problem is that the existing HTML always gets omitted if it contains any {{angular template code}}.

How do I write the directive so that it still honors the template code?

4
  • Any reason your not using transclude? Also any reason your building your HTML in a JS String instead of having static HTML with angular bindings? Commented Apr 9, 2014 at 20:28
  • yes and yes. transclude has and has not been used, it didn't do what I expected either way, so I figured someone with transclude expertise would say something in response to this question. js string instead of angular binding: i was just doing this so i could write conditions outside of the template code. but also, in the context of angular, i'm not sure if you mean bindings as in using ng-bind or bindings in the sense that i should use {{bindings}}. can you show me an example of what you'd do here... as an answer? Commented Apr 9, 2014 at 21:50
  • Take a look at the eggheadIO video on components and containers: egghead.io/lessons/angularjs-components-and-containers John's example of containers seems like it would do what you need. Commented Apr 10, 2014 at 13:58
  • thanks for the video, it was just enough information that I needed in order to start asking the right questions. Commented Apr 11, 2014 at 16:18

1 Answer 1

5

Ive successfully fixed the issue with the directive, but it took several steps.

  1. Use the correct scope properties. instead of using '=', I used '@'

    That was based on the following link: What is the difference between '@' and '=' in directive scope in AngularJS?

    The thing to note about scope isolation using @, =, and & affects the way you must refer to the variable in the template. for example, using = means that I would refer the variable without brackets while using @ would refer to the variable with {{brackets}}.

  2. Like I mentioned in the first point, after adjusting the scope properties, i needed to go back and refer to the variables in the correct way depending on how the scope was defined.

  3. ng-transclude when used with {...transclude: true,...} requires that I actually put a container somewhere in the template for that transcluded content. Here's an example of that:

    return ['<div class="section row short" '+color+' ng-transclude>',
      title,
        '<div ng-transclude>', //this is the container for the original innerHTML, transcluded
            content, //this may contain {{template code}}, and gets transcluded
        '</div>
      '</div>'
    ].join("\n");
    

Only then did the directive work as expected. Also, props to @rob for providing me with this introductory link, https://egghead.io/lessons/angularjs-components-and-containers.

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

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.