Saturday, 14 September 2013

Transcluding Attributes in an Angular Directive

Transcluding Attributes in an Angular Directive

I was creating a select replacement directive to make it easy to style up
selects according to the design without having to always right a bunch of
markup (i.e. the directive does it for you!).
I didn't realize that attributes don't transclude to where you put
ng-transclude and just go to the root element.
I have an example here: http://plnkr.co/edit/OLLntqMzbGCJS7g7h1j4?p=preview
You can see that it looks great... but there's one major flaw. The id and
name attributes aren't being transferred. Which, ya know, without name, it
doesn't post to the server (this form ties into an existing system, so
AJAXing the model isn't an option).
For example, this is what I start with:
<select class="my-select irrelevant-class" name="reason" id="reason"
data-anything="banana">
<option value="">Reason for Contact...</option>
<option>Banana</option>
<option>Pizza</option>
<option>The good stuff</option>
<option>This is an example of a really, really, really, really,
really, really long option item</option>
</select>
...this is what I want it to look like:
<div class="faux-select" ng-class="{ placeholder: default == viewVal,
focus: obj.focus }">
<span class="faux-value">{{viewVal}}</span>
<span class="icon-arrow-down"></span>
<select ng-model="val" ng-focus="obj.focus = true" ng-blur="obj.focus
= false" ng-transclude class="my-select irrelevant-class"
name="reason" id="reason" data-anything="banana">
<option value="">Reason for Contact...</option>
<option>Banana</option>
<option>Pizza</option>
<option>The good stuff</option>
<option>This is an example of a really, really, really, really,
really, really long option item</option>
</select>
</div>
...but this is what actually happens:
<div class="faux-select my-select" ng-class="{ placeholder: default ==
viewVal, focus: obj.focus }" name="reason" id="reason"
data-anything="banana">
<span class="faux-value">{{viewVal}}</span>
<span class="icon-arrow-down"></span>
<select ng-model="val" ng-focus="obj.focus = true" ng-blur="obj.focus
= false" ng-transclude>
<option value="">Reason for Contact...</option>
<option>Banana</option>
<option>Pizza</option>
<option>The good stuff</option>
<option>This is an example of a really, really, really, really,
really, really long option item</option>
</select>
</div>
Specifically, the issue is that there's no name attribute on the select,
so it doesn't actually send the data to the server.
Obviously, I can use a pre-compile phase to transfer the name and id
attributes (that's what I am doing for now), but it would be nice if it
would just automatically transfer all of the attributes so they can add
any classes, arbitrary data, (ng-)required, (ng-)disabled attributes, etc,
etc.
I tried getting transclude: 'element' to work, but then I couldn't the
other attributes from the template onto it.
Note, I saw the post here: How can I transclude into an attribute?, but it
looks like they just manually transfer the data, and I am aiming to get it
to auto-transfer all the attributes.

No comments:

Post a Comment