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?