2

I am trying to create a directive that can create multiple elements an replace the calling element with the multiple. Specifically I want to set the directive on a single list-item and have it create multiple list items w/o a wrapping element. (Using the <UL> for the directive works but prevent me from including 'static' items.) Here is the markup:

<ul>
    <li>static first</li>
    <li my-repeater="myVar"></li>
    <li>static last</li>
</ul>

In my controller I'll define myVar:

$scope.myVar = ['one', 'two', 'three'];

And my directive looks like this:

myApp.directive('myRepeater', function () {
    return {
        restrict: 'A',
        transclude: 'element',
        replace: true, //<--- DEPRECATED 
        scope: {
            val: '=myRepeater'
        },
        template: '<li ng-repeat="item in val">{{item}}</li>'
    };
};

In AngularJS v1.2.26 this works UNLESS you remove 'replace', then you get nothing. Is this just not possible? I did note that in the docs for v1.3.4 that they feel:

There are very few scenarios where element replacement is required for the application function, ...

But my case above seems to be a clear example of the need for this, unless there is a 'better way'!...?

5
  • I've posted a fiddle of the example above here Commented Nov 24, 2014 at 17:00
  • 1
    What's preventing you from using ng-repeat right in the template? Commented Nov 24, 2014 at 17:06
  • It's deprecated, not removed. Just use it and wait for Angular 2.0 to come out then see what they suggest for migration Commented Nov 24, 2014 at 17:10
  • @AlexG , I like the pragmatism of this and would go with it but in this case our dev team has made a decision to avoid the deprecated items. Commented Nov 25, 2014 at 14:13
  • @hon2a simply using ng-repeat was my first preference (KISS Rule!) but we have a certain amount of logic around the actual choices in our actual case so my goal was to encapsulate that in a directive. Commented Nov 25, 2014 at 14:16

1 Answer 1

2

If you don't have to do it as an attribute, then you can do it using an element:

<div ng-app="myApp">
    <div ng-controller="MyCtrl">
        <ul>
            <li>static first</li>
            <my-repeater var="myVar"></my-repeater>
            <li>static last</li>
        </ul>
    </div>
</div>

And the directive

    .directive('myRepeater', function () {
    return {
        restrict: 'E',
        scope: {
            val: '=var'
        },
        template: '<li ng-repeat="item in val">{{item}}</li>'
    };
    })

I updated the fiddle to show it http://jsfiddle.net/6rjr8nq5/1/

Since unknown tags are just ignored, it works fine.

And if you need the attribute, you could stick it on the ul, transclude, and use the link function to properly place the static data, assuming you know where it goes.

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

6 Comments

And no idea why someone downvoted the answer without at least commenting what their issue was....
Me neither, I ran this solution and it worked just fine with the only caveat being that it results in extraneous markup that some purists may not like (validation issues, maybe?) but that's not a big deal to me.
True, it is extraneous markup, but it works. And if someone doesn't like extraneous markup, then the entire Angular directives for "element" is invalid. I will take this.
Selecting this answer as it's the most directly relevant solution I've found. It's working well in our actual case, too, thanks.
I wanted to write "HTH" but it was too short for a comment, so... Happy to Help.
|

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.