Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Customizing the template within a Directive

I have a form that is using markup from Bootstrap, like the following:

<form class="form-horizontal">   <fieldset>     <legend>Legend text</legend>     <div class="control-group">       <label class="control-label" for="nameInput">Name</label>       <div class="controls">         <input type="text" class="input-xlarge" id="nameInput">         <p class="help-block">Supporting help text</p>       </div>     </div>   </fieldset> </form> 

There's a lot of boilerplate code in there, that I'd like to reduce to a new directive - form-input, like follows:

<form-input label="Name" form-id="nameInput"></form-input> 

generates:

   <div class="control-group">       <label class="control-label" for="nameInput">Name</label>       <div class="controls">         <input type="text" class="input-xlarge" id="nameInput">       </div>     </div> 

I have this much working via a simple template.

angular.module('formComponents', [])     .directive('formInput', function() {         return {             restrict: 'E',             scope: {                 label: 'bind',                 formId: 'bind'             },             template:   '<div class="control-group">' +                             '<label class="control-label" for="{{formId}}">{{label}}</label>' +                             '<div class="controls">' +                                 '<input type="text" class="input-xlarge" id="{{formId}}" name="{{formId}}">' +                             '</div>' +                         '</div>'          }     }) 

However it's when I come to add in more advanced functionality that I'm getting stuck.

How can I support default values in the template?

I'd like to expose the "type" parameter as an optional attribute on my directive, eg:

<form-input label="Password" form-id="password" type="password"/></form-input> <form-input label="Email address" form-id="emailAddress" type="email" /></form-input> 

However, if nothing is specified, I'd like to default to "text". How can I support this?

How can I customize the template based on the presence / absence of attributes?

I'd also like to be able to support the "required" attribute, if it's present. Eg:

<form-input label="Email address" form-id="emailAddress" type="email" required/></form-input> 

If required is present in the directive, I'd like to add it to the generated <input /> in the output, and ignore it otherwise. I'm not sure how to achieve this.

I suspect these requirements may have moved beyond a simple template, and have to start using the pre-compile phases, but I'm at a loss where to start.

like image 270
Marty Pitt Avatar asked May 17 '12 02:05

Marty Pitt


People also ask

Can a directive have templates?

Components are directives with templates. The only difference between Components and the other two types of directives is the Template. Attribute and Structural Directives don't have Templates.

What is a custom directive?

Custom directives are used in AngularJS to extend the functionality of HTML. Custom directives are defined using "directive" function. A custom directive simply replaces the element for which it is activated.

Which directive can have a template in Angular?

Angular creates the directive class and specifies the CSS selector, appUnless , that identifies the directive in a template. Import Input , TemplateRef , and ViewContainerRef . Inject TemplateRef and ViewContainerRef in the directive constructor as private variables.


1 Answers

angular.module('formComponents', [])   .directive('formInput', function() {     return {         restrict: 'E',         compile: function(element, attrs) {             var type = attrs.type || 'text';             var required = attrs.hasOwnProperty('required') ? "required='required'" : "";             var htmlText = '<div class="control-group">' +                 '<label class="control-label" for="' + attrs.formId + '">' + attrs.label + '</label>' +                     '<div class="controls">' +                     '<input type="' + type + '" class="input-xlarge" id="' + attrs.formId + '" name="' + attrs.formId + '" ' + required + '>' +                     '</div>' +                 '</div>';             element.replaceWith(htmlText);         }     }; }) 
like image 177
Misko Hevery Avatar answered Sep 29 '22 13:09

Misko Hevery