How to apply font-family in ng-option for each option

谁说胖子不能爱 提交于 2019-12-11 00:01:56

问题


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.


回答1:


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

  1. 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>
  1. Add a callback in the optionsAttributeTransform directive that returns an json object that represents the attributes to be appended in each of the options 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);



回答2:


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.



来源:https://stackoverflow.com/questions/33951405/how-to-apply-font-family-in-ng-option-for-each-option

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!