Skip to content

Instantly share code, notes, and snippets.

Created July 27, 2015 07:09
Show Gist options
  • Save anonymous/90c1aa1f830a0d5dba7b to your computer and use it in GitHub Desktop.
Save anonymous/90c1aa1f830a0d5dba7b to your computer and use it in GitHub Desktop.
Custom CSS Angular radio button
<p>Base from <a href="https://docs.angularjs.org/api/ng/input/input%5Bradio%5D">https://docs.angularjs.org/api/ng/input/input%5Bradio%5D</a></p>
<p>My problem is that adding custom styling to a radio button is usually derived from a class on the label element. With vanilla js or jquery I would put a "selected" class on the label element of the input, by binding to the onclick of the input.
<br/> Then I would hide the input with CSS and add a custom before/bg image to the label. But I don't know if this can be done easier in Angular, by relying on the model.</p>
<h1>ng-class</h1>
<p>Leveraging ng-class helps, although it can probably be done simpeler by a directive, but it would move input to a template and is a lot more complicated.</p>
<div ng-app="radioExample">
<form name="myForm" ng-controller="ExampleController">
<label ng-class="{selected: color.name === 'red'}">
<input type="radio" ng-model="color.name" value="red"> Red
</label>
<br/>
<label ng-class="{selected: color.name === 'green'}">
<input type="radio" ng-model="color.name" value="green"> Green
</label>
<br/>
<!--<label>
<input type="radio" ng-model="color.name" ng-value="specialValue">
Green
</label><br/>-->
<label ng-class="{selected: color.name === 'blue'}">
<input type="radio" ng-model="color.name" value="blue"> Blue
</label>
<br/>
<br/>
<tt>selected color = {{color.name | json}}</tt>
<br/>
</form>
<!--Note that `ng-value="specialValue"` sets radio item's value to be the value of `$scope.specialValue`.-->
<h1>Custom directive</h1>
<div ng-controller="CustomRadioController" class="directive">
<ul>
<li>
<radio model="myDirection.name" value="'top'"><i class="top"></i>Top</radio>
</li>
<li>
<radio model="myDirection.name" value="'front'">Front</radio>
</li>
<li>
<radio model="myDirection.name" value="'right'"><i class="right"></i>Right</radio>
</li>
</ul>
<br/>
<tt>selected direction = {{myDirection.name | json}}</tt>
</div>
</div>
angular.module('radioExample', [])
.controller('ExampleController', ['$scope', function($scope) {
$scope.color = {
name: 'red'
};
/*$scope.specialValue = {
"id": "12345",
"value": "green"
};*/
}])
.controller('CustomRadioController', ['$scope', function($scope) {
$scope.myDirection = {
name: 'top'
};
}])
.directive('radio', function() {
return {
restrict: 'E',
transclude: true,
scope: {
model: '=',
value: '='
},
template: '<label ng-class="labelClass">' +
'<input type="radio" ng-model="model" ng-value="value" />' +
'<span ng-transclude></span>' +
'</label>',
link: function(scope) {
scope.$watch('model', function(newValue) {
scope.labelClass = scope.model === scope.value ? 'selected' : ''; //scope.model === scope.value;
});
}
};
});
<script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.3.14/angular.min.js"></script>
body, html {
font-family: Arial;
}
form {
margin-top: 2em;
}
[name=myForm] .selected {
background: red;
}
.directive {
$border: #444;
$bg: #ccc;
color: $border;
ul {
border: 1px solid $border;
border-radius: 0.2em;
background-color: $bg;
background: linear-gradient(to bottom, $bg 0%, darken($bg, 5%) 56%, darken($bg, 10%) 100%);
display: inline-block;
font-size: 2em;
padding-left: 0;
> li {
display: inline-block;
&:first-child label {
border-bottom-left-radius: 0.2em;
border-top-left-radius: 0.2em;
}
&:last-child label {
border-bottom-right-radius: 0.2em;
border-top-right-radius: 0.2em;
}
}
}
label {
background-color: $bg;
background: linear-gradient(to bottom, $bg 0%, darken($bg, 5%) 56%, darken($bg, 10%) 100%);
cursor: pointer;
display: inline-block;
padding: 0.5em;
text-align: center;
width: 3.5em;
input {
display: none;
}
&.selected {
background-color: darken($bg, 20%);
background: linear-gradient(to bottom, darken($bg, 20%), darken($bg, 25%) 56%, darken($bg, 30%) 100%);
color: lighten($bg, 5%);
transition: background 1s;
.top::before {
border-top: 20px solid lighten($bg, 5%);
}
.right::before {
border-left: 20px solid lighten($bg, 5%);
}
}
i {
&::before {
content: '';
display: inline-block;
font-style: normal;
height: 0;
margin-right: 4px;
width: 0;
}
&.top::before {
border-top: 20px solid $border;
border-left: 10px solid transparent;
border-right: 10px solid transparent;
}
&.right::before {
border-top: 10px solid transparent;
border-left: 20px solid $border;
border-bottom: 10px solid transparent;
}
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment