3

Consider this example:

<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-rc.4/angular.js"></script>
<script>
angular.module('app', [])
</script>
<div ng-app='app'>

<div ng-init="tags  = ['i', 'b', 't']">
<div ng-repeat = 't in tags'>{{t}}</div>

</div>
</div>

Demo

This works as supposed, however I would like to be able to specify the element or attribute.

<div ng-init="tags  = ['i', 'b', 't']">
<{{t}} ng-repeat = 't in tags'>{{t}}</{{t}}>

This doesn't work: Demo

How can I do this? I basicly want to build a html-structure (with my own directives) from json. Is it good or bad best practise to do this?

3 Answers 3

2

You can use a directive with a custom transclusion function to achieve this :

.directive('bindTagName', ['$compile', function ($compile) {
    return {
        transclude: true,
        replace: true,
        link: function (scope, elem, attrs, controller, transcludeFn) {
            // get tag name
            var tagName = scope.$eval(attrs.bindTagName);

            // create new tag
            var created = angular.element(document.createElement(tagName));

            // replace current element with created tag
            elem.replaceWith(created);

            // call transclude function
            transcludeFn(
                function (clone, scope) {
                    $compile(created.append(clone))(scope);
                }
            );
        }
    }
}])

Given the following view :

<div ng-init="tags  = ['i', 'b', 't']">
    <div ng-repeat = 't in tags' bind-tag-name="t">-&gt; {{t}}</div>
</div>

It will produce the following html :

<div ng-init="tags  = ['i', 'b', 't']">
    <!-- ngRepeat: t in tags -->
    <i><span class="ng-binding ng-scope">-&gt; i</span></i>
    <!-- end ngRepeat: t in tags -->
    <b><span class="ng-binding ng-scope">-&gt; b</span></b>
    <!-- end ngRepeat: t in tags -->
    <t><span class="ng-binding ng-scope">-&gt; t</span></t>
    <!-- end ngRepeat: t in tags -->
</div>
Sign up to request clarification or add additional context in comments.

4 Comments

Thanks, but this doesn't work with custom directives: plnkr.co/edit/LQ0s2DfpivvTZhDWGy4w?p=preview Also the elements are surrounded with <span class="ng-binding ng-scope">b</span> -ish stuff.
As you see in the plnkr, the bindTagName-directive is unable to create the directive 'test'.
Thanks, now it works as expected. But I have a question, when I look at the component in developer tools it looks like this: <b class="ng-scope"><span class="ng-binding ng-scope">b</span><br class="ng-scope"></b>. Why does it get wrapped like this? Is there anyway to avoid it? Demo: plnkr.co/edit/LQ0s2DfpivvTZhDWGy4w?p=preview
Looks like to be default behavior : groups.google.com/forum/#!topic/angular/5SaF085FANw
0

I don't know if you can manipulate the HTML tags themselves with angular. However I can think of something that would work:

<div ng-app="app" ng-controller="appController">
    <div ng-init="tags = ['i', 'b', 't']">
        <i ng-show="t == 'i'" ng-repeat ="t in tags">{{t}}</i>
        <br/>
        <b ng-show="t == 'b'" ng-repeat ="t in tags">{{t}}</b>
        <br/>
        <t ng-show="t == 't'" ng-repeat ="t in tags">{{t}}</t>
        <br/>
    </div>
</div>

I'm not sure this would solve your problems. For each tag you would like to used you have to write that tag and just show it or hide it depending on input.

example in JSFiddle.

1 Comment

That is great, but what if i have hundreds of different directives? Or if I change the name of a directive, I have to change this as well. I want to avoid putting too much logic in html.
0

You could do something like the following:

<div ng-init="tags = ['span', 'span', 'div']">
   <span ng-repeat="t in tags track by $index" 
         ng-bind-html="'<' + t + '>' + t + '</' + t + '>'">
   </span>
</div>

but, that will add a wrapping <span> element.

EDIT: this requires adding a reference to angular-sanitize.js and adding a module dependency to your app, such that it would automatically sanitize the unsafe HTML:

angular.module("myApp", ["ngSanitize"])

2 Comments

Thanks, but this doesn't work for custom directives, also you need to filter to unsafe html. plnkr.co/edit/1py7Iuc3cEz5FfRN0Rvv?p=preview
you don't need to filter explicitly like you did in your plunker - just add "ngSanitize" as your module dependency. And, if by "custom directives" you mean that it won't compile angular code, then yes - this would not work and you should follow the directive approach suggested in another answer.

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.