2
\$\begingroup\$

I found creating radio buttons in my application a bit of a hassle in terms of having to configure the HTML to do what I wanted when the user clicks/unclicks the items etc.

I figured reducing it to a directive was the best way to simplify things.

The functionality I want is:

  • Be able to pass in a list of items that are displayed as radio button options
  • Be able to specify which item is checked by default
  • Can be displayed as a horizontal or vertical list
  • Have the option to make the buttons unselectable (i.e. clicking them again will uncheck the item)
  • The controller knows which value is checked.
  • The controller executes a function when the checked value changes
  • The controller can change which item is checked

Here is a working plunker.

Here is an example usage of the directive:

<dwj-radio-group 
 dwj-items = "items"
 dwj-changefn = "changeFn"
 dwj-unselectable = "true"
 dwj-align = "vertical"
 dwj-boundvalue = "foo"
 >
</dwj-radio-group>

Here is the directive code:

var radioDirective = app.directive('dwjRadioGroup', function($compile, $templateCache ) {
 var getTemplate = function(item){
 var template = 'ERROR'; 
 console.log(item);
 switch (item){
 case 'horizontal':
 template = $templateCache.get("radio-group-horizontal.html");
 break;
 case 'vertical':
 template = $templateCache.get("radio-group-vertical.html");
 break; 
 }
 return template; 
 };
 return {
 scope : {
 items : '=dwjItems',
 changeFn : '=dwjChangefn',
 selectedItem: "=dwjBoundvalue",
 unselectable: "=dwjUnselectable", 
 align: "=dwjAlign"
 },
 link : function(scope, element, attrs) {
 scope.unselectable =scope.unselectable === 'true'; //default false
 scope.align = scope.align === "vertical"? "vertical": "horizontal"; //default horizontal
 //http://onehungrymind.com/angularjs-dynamic-templates/ 
 var content = getTemplate(scope.align);
 console.log(content);
 element.html(content);
 $compile(element.contents())(scope);
 scope.changeItem = function(x){
 if (scope.unselectable && x === scope.selectedItem){ 
 scope.selectedItem = null; 
 } 
 else{ 
 scope.selectedItem = x; 
 } 
 scope.changeFn(scope.selectedItem);
 };
 }
 };
});

Currently, from what I can see, the directive does everything I want it to.

I'm looking for feedback on my use of the directive:

  • Are my naming conventions correct?
  • Am I using the directive scope binding correctly?
  • Is using $templateCache and $compile a good way to do this, or is there a much simpler way to do it?
  • Is there anything completely broken that I'm missing?
Jamal
35.2k13 gold badges134 silver badges238 bronze badges
asked Feb 27, 2016 at 6:15
\$\endgroup\$

1 Answer 1

1
\$\begingroup\$
items : '=dwjItems',
changeFn : '=dwjChangefn',
selectedItem: "=dwjBoundvalue",
unselectable: "=dwjUnselectable", 
align: "=dwjAlign"

Your indentation needs some work.

scope : {
 items : '=dwjItems',
 changeFn : '=dwjChangefn',
 selectedItem: "=dwjBoundvalue",
 unselectable: "=dwjUnselectable", 
 align: "=dwjAlign"
},

Not sure why you need to prefix "dwj" to your directive attributes. It's not like it will collide with anything else. Besides, you're using the directive as an element. No potential DOM attribute name collisions.

scope.unselectable =scope.unselectable === 'true'; //default false
scope.align = scope.align === "vertical"? "vertical": "horizontal"; //default horizontal
//http://onehungrymind.com/angularjs-dynamic-templates/ 
var content = getTemplate(scope.align);
console.log(content);
element.html(content);
$compile(element.contents())(scope);

Not entirely sure why you need to dynamically compile the template. You can simply just define both layouts in the same template and hide one of them when the other is selected. You can use ng-if for that. A developer can come in and say "Oh, two layouts for a directive" than "Oh, I have to take care of 2 template files."

answered Feb 27, 2016 at 13:29
\$\endgroup\$
1
  • \$\begingroup\$ could you please elaborate a little bit more on the indentation issue? \$\endgroup\$ Commented Feb 27, 2016 at 15:00

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.