最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Angular directive with passed innerHTML containing template code - Stack Overflow

programmeradmin3浏览0评论

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?

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?

Share Improve this question asked Apr 9, 2014 at 18:36 KristianKristian 21.9k19 gold badges108 silver badges184 bronze badges 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? – rob 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? – Kristian Commented Apr 9, 2014 at 21:50
  • Take a look at the eggheadIO video on ponents and containers: egghead.io/lessons/angularjs-ponents-and-containers John's example of containers seems like it would do what you need. – rob 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. – Kristian Commented Apr 11, 2014 at 16:18
Add a ment  | 

1 Answer 1

Reset to default 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-ponents-and-containers.

发布评论

评论列表(0)

  1. 暂无评论