Custom select directive for styling & padding

by Ayyappan Sakthivadivel

HTML

<script src="https://cdn.rawgit.com/epeli/underscore.string/master/dist/underscore.string.min.js"></script>
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/font-awesome/4.6.3/css/font-awesome.min.css">
<div ng-app="demoApp" ng-controller="mainCtrl as ctrl">
    <h3>
    Custom directive styled as select with table for padding
    </h3>
    <my-select ng-model="ctrl.selection" data="ctrl.selectData"></my-select>
    <br/> {{ctrl.selection}}
    <h3>
    Select with ng-repeat and formtString method
    (updating not working properly)
    </h3>
    <select ng-model="ctrl.selection">
        <option ng-repeat="trink in ctrl.selectData" ng-bind-html="ctrl.formatString(trink)" value="{{trink}}"></option>
    </select>

    <h3>
    Select wiht ng-options (no padding)
    </h3>
    <select ng-model="ctrl.selection" ng-options="trink as (trink.name+ ' ' + trink.size + ' ' + trink.units) for trink in ctrl.selectData"></select>

    <script type="text/ng-template" id="components/selectionDirTmpl.html">
        <div class="selectBox" ng-click="selectCtrl.open()">
            <div class="selectBox-title">{{selectCtrl.selection}}
                <i class="fa fa-chevron-down pull-right chevron-box" id="test" aria-hidden="true"></i>
            </div>
            <table ng-if="selectCtrl.visible">
                <tr ng-repeat="item in selectCtrl.data">
                    <td ng-repeat="(key,value) in item" colspan="{{key === 'empty'? Utils.keys(selectCtrl.data[1]).length - 1: ''}}" ng-click="selectCtrl.select(item)">{{value}}</td>
                </tr>
            </table>
        </div>
    </script>
</div>

CSS

select {
    font-family: "Lucida Console", Monaco, monospace;
    /*white-space: pre;*/
}

.selectBox {
    position: relative;
    font-family: Arial, Helvetica Neue, Helvetica, sans-serif;
    width: 250px;
    cursor: default;
}

.selectBox-title {
    border: 1px solid lightgray;
    padding: 0.5em;
    line-height: 1em;
    min-height: 1em;
}

div .selectBox-title:hover {
    border: 1px solid black;
}

.selectBox table {
    width: 100%;
    position: absolute;
    top: 2em;
    left: 0;
    border-collapse: collapse;
    background-color: rgba(255, 255, 255, 0.9);
    border: 1px solid gray;
    padding: 0.5em;
    white-space: pre;
}

.selectBox tr:hover {
    background-color: lightblue;
}

.selectBox td {
    padding: 0.5em;
}

.pull-right {
    float: right;
}

JavaScript

// for this SO
// http://stackoverflow.com/questions/37768742/how-to-make-hmtl-markup-show-correctly-in-angularjs-binding-using-a-function/37768855#37768855
angular.module('demoApp', [])
    .directive('mySelect', MySelectDir)
    .controller('mainCtrl', MainCtrl);

function MySelectDir($document, $parse) {
    return {
        scope: {
            ngModel: '=',
            data: '='
        },
        controllerAs: 'selectCtrl',
        controller: function($scope, $element, $attrs) {
            var vm = this,
            	localData = Object.create($scope.data); // use local copy so we can add empty option
                
			$scope.Utils = {
                 keys : Object.keys
            };
            //$scope.data = angular.copy($scope.data);
            
            function dismissClick(e) {
                if ($element !== e.target && !$element[0].contains(e.target)) {
                    console.log('dismiss', vm.visible);
                    vm.visible = false;
                    $document.off('click', dismissClick);
                    $scope.$apply();
                }
            }

            function createCaption(model) {
                var caption = '';
                angular.forEach(model, function(value, key) {
                    if (key !== '$$hashKey' && value !== null) {
                        caption += ' ' + value;
                    }
                });
                return caption;
            }

            angular.extend(vm, {
                visible: false,
                data: localData,
                selection: {},
                select: function(item) {
                    var index = vm.data.indexOf(item);
                    $scope.ngModel = vm.data[index].empty === null ? {} :
                        vm.data[index];
                    vm.selection = createCaption(vm.data[index]);
                },
                addDismissClick: function() {
                    $document.on('click', dismissClick);
             ...