I want to show a combobox whose all option font will be different.
When using the ng-options
directive in AngluarJS to fill in the options for a <select>
tag I cannot figure out how to set the font-family for each option.
$scope.reportFontload=["Andale Mono","Arial","Arial Black","Bitstream Charter","Century Schoolbook L","Comic Sans MS","Courier 10 Pitch","Courier New","DejaVu Sans"];
<select ng-options="font for font in reportFontload" ng-model="selected">
<option value="" disabled selected>Font Family</option>
</select>
For ng-repeat if i use to apply style="font-family:{{font}}"
. It works for each and every option in the ng-repeat
.
Here is the example: fiddle
<select ng-model="selected">
<option value="" disabled selected>Fonts</option>
<option ng-repeat="font in reportFontload" value={{font}} style="font-family:{{font}}">{{font}}</option>
</select>
I need to know , Why font-family is not works in ng-option
. Guide me any possible answer.
I have created an optionsAttribute
directive that can transform the attributes of your option tags after they are rendered by ngOptions
.
DEMO
Directive
.directive('optionsAttribute', function($parse, $timeout) {
return {
restrict: 'A',
compile: function(tElem, tAttr) {
var transform = $parse(tAttr.optionsAttributeTransform);
return function(scope, elem, attr) {
scope.$watch(attr.optionsAttribute, function(data) {
var options = elem.children();
options = Array.prototype.slice.call(options, options.length - data.length);
angular.forEach(options, function(option, index) {
var optionElement = angular.element(option);
var newAttribute;
var label;
if(angular.isDefined(attr.optionsAttributeTransform)) {
newAttribute = transform(scope, {
$data: data[index],
$label: option.innerHTML,
$index: index
});
angular.forEach(newAttribute, function(value, attribute) {
optionElement.attr(attribute, value);
});
}
});
});
};
}
};
});
Usage
- Provide the array value you have provided in the
ngOptions
directive in the optionsAttribute
directive.
e.g.
<select ng-options="font for font in reportFontload"
options-attribute="reportFontload">
</select>
- Add a callback in the
optionsAttributeTransform
directive that returns an json object that represents the attributes to be appended in each of the option
s tag. The callback itself is provided with 2 values:
$data - represents each of the item in the array provided in #1.
$index - represents the index of the $data
.
e.g.
HTML
<select ng-options="font for font in reportFontload"
ng-model="selected"
options-attribute="reportFontload"
options-attribute-transform="{ 'style': 'font-family: ' + $data }">
</select>
or an alternative is to provide a function callback
JAVASCRIPT
$scope.transform = function(fontFamily) {
return { 'style': 'font-family ' + fontFamily };
};
HTML
<select ng-options="font for font in reportFontload"
ng-model="selected"
options-attribute="reportFontload"
options-attribute-transform="transform($data)">
</select>
LIMITATIONS
The directive is only limited towards array, objects excluded, although there is a way to tweak the current directive to also work with objects, but the current implementation is already sufficient for the OP's problem.
UPDATE
I tweaked the directive above to also work with object collections, the usage still says the same:
DEMO
(function(ng) {
'use strict';
var app = ng.module('options.attribute', []);
app.directive('optionsAttribute', function($parse) {
return {
restrict: 'A',
compile: function(tElem, tAttr) {
var transform = $parse(tAttr.optionsAttributeTransform);
return function(scope, elem, attr) {
scope.$watch(attr.optionsAttribute, function(collection) {
var options = elem.children();
collection = new Collection(collection);
options = Array.prototype.slice.call(options, options.length - collection.getLength());
ng.forEach(options, function(option, index) {
var newAttributes = transform(scope, {
$data: collection.getItem(index),
$label: option.innerHTML,
$index: collection.getIndex(index)
});
var optionElement = angular.element(option);
ng.forEach(newAttributes, function(value, attribute) {
optionElement.attr(attribute, value);
});
});
}, true);
};
}
};
});
function Collection(collection) {
var self = this;
var indexes;
if(angular.isObject(collection)) {
if(Object.keys) {
indexes = Object.keys(collection);
} else {
ng.forEach(collection, function(item, index) {
indexes.push(index);
});
}
self.getItem = function(index) {
return collection[indexes[index]];
};
self.getLength = function() {
return indexes.length;
};
self.getIndex = function(index) {
return indexes[index];
};
} else if(angular.isArray(collection)) {
self.getItem = function(index) {
return collection[index];
};
self.getLength = function() {
return collection.length;
};
self.getIndex = function(index) {
return index;
};
}
}
})(angular);
You can not create a select(combo box) whose options will have different font. As per my knowledge this is not allowed in HTML and CSS.
But you can achive this if you use different commbo like: Bootstrap or some other this.
Here is a bootstrap example with plain HTML.
<div class="dropdown">
<button class="btn btn-default dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="true">
Dropdown
<span class="caret"></span>
</button>
<ul class="dropdown-menu" aria-labelledby="dropdownMenu1">
<li style="font-family:Arial"><a href="#">Action</a></li>
<li style="font-family:Arial Blackl"><a href="#">Another action</a></li>
<li style="font-family:Andale Mono"><a href="#">Something else here</a></li>
<li style="font-family:Courier New"><a href="#">Separated link</a></li>
</ul>
</div>
Plunker Here
Now for usage in angular you may use https://angular-ui.github.io/bootstrap/
Or you can write your own implementation for it.