The ability to reply to discussions is limited to PRO members. Want to join in the discussion? Click here to subscribe now.

Directive with Transcluded Elements

Directive with Transcluded Elements

4:46
Create a `wrapWith` directive using advanced transclusion techniques.
Watch this lesson now
Avatar
egghead.io

Create a wrapWith directive using advanced transclusion techniques.

Avatar
Andy

This lesson is fantastic. Angular tutorials that tackle anything above a beginner level are very hard to find. As you stated, the use cases for this are not as common as the more basic things, but when you're writing real applications, they do come up. More lessons like this one would be very beneficial to me. I'm sure I'm not alone. Thanks for the great tutorial!

Avatar
Lukas

The code do not work form me (I'am using exactly the same code as you posted).
I got error: Error: [jqLite:nosel] http://errors.angularjs.org/1.2.10/jqLite/nosel
on
the line

var templateElement = angular.element(template)

The problem is that template contains new lines "\n <div style="color: red"></div>\n". Quick fix is angular.element(template.trim()). But it looks like angular bug for me.

Avatar
Joel

Interesting, I wonder if that is from cut-n-paste?

Thanks for posting the solution. That's an annoying bug :>

In reply to Lukas
Avatar
Lukas

As you ask "I wonder if that is from cut-n-paste?"
No definitely not. It's bug in angular 1.2.10. Change version to the 1.2.12 fix it. I guess taht this commit fix it: https://github.com/angular/angular.js/commit/36d37c0e3880c774d20c014ade60d2331beefa15

In reply to Joel
Avatar
Kasper

This fits nicely into what I'm trying to do at the moment, wrapping an input element with an outer div and appending into that another element (a label for said input).

However, I'm at a loss on how to apply ng-model validations to the transcluded element. I've made it work going the non-transcluding way, simply creating elements in the linking function and rearranging the dom - however, the transclude way is way nicer on the eye and makes more 'sense' to me.

Any comments on how you would adhere to validations?

The input element in question looks something like this:

input type="text" wrap-directive="LabelText" ng-model="someModel.name" required="required"

Cheers, and thanks for the great lessons!

In reply to egghead.io
Avatar
Bashar

how to include angular expression {{ }} with the template and pass the value with another directive, like below:

.
.


{{ formTitle }}

egghead.directive("wrapWith", function ($templateCache) {
return {
transclude: 'element',
scope: {
formTitle: '@'
},
link: function (scope, element, attrs, ctrl, transclude) {
var template = $templateCache.get(attrs.wrapWith);
console.log(template);

var templateElement = angular.element(template);

        console.log(element);

        transclude(scope, function (clone) {
            element.after(templateElement.append(clone));
        })
    }
}

})

I tried but that didn't work,

Please advice,

In reply to egghead.io
Avatar
Alexander

Hey John, I have been using the concepts outlined in this video but have stumbled upon something I am not exactly sure how to do.

I am trying to wrap a form input with an ng-model, but the ng-model seems to stop working.

Here is a Plunker of my strategy:

http://plnkr.co/edit/AUbB4BYGrdGr7Mhx0a9c?p=preview

Avatar
John

http://plnkr.co/edit/ctJCY2u0XIJxFVsRVWgC?p=preview

A few things:
* "input" and "ng-model" are both directives which will fight for compile "priority" with your "wrapper" directive. So make sure to bump up your "priority" > 0.
* You don't need "scope.$parent" in your transclude call because transclusion already uses the appriopriate scope by default.
* Look where I used "ng-init" in my .html and move that model into a controller. Only using "name" instead of "model.name" will break with your approach (rewatch "the dot" video).

In reply to Alexander
Avatar
Alexander

John, thanks for replying. Pretty awesome that you personally do so.

With this approach, the model always has to be predeclared in the controller through either "ng-init" but more realistically scope.model = {}. Is this a best practice? In the past, I usually did input ng-mode="newUser.firstName"/ without necessarily declaring it in the scope first.

In reply to John
Avatar
John

I would put it on the scope first. Letting AngularJS create objects in the HTML is a little too "magical" for me in real applications.

In reply to Alexander
HEY, QUICK QUESTION!
Joel's Head
Why are we asking?