使用AngularJs通过指令

时间:2016-06-27 13:46:33

标签: javascript html angularjs

我有一个下拉框,显示一些任意键值对。问题是在范围内只有密钥驻留,并且必须翻译到相应的密钥值对中。

到目前为止,我有一个非常(至少对我来说)好看的解决方案,你可以在这里检查JSFiddle

在我的HTML代码中,我想写下这样的内容:

<div data-ng-app="myApp" ng-strict-di>
    <div data-ng-controller="myController">
        <select as-relative-ranking data-ng-model="myRating">
        </select>
    </div>
</div>

我的控制代码看起来像这样:

app.controller('myController', ['$scope', function($scope) {
    $scope.myRating = 2;
}]);

为了获得键值对之间的链接,我编写了以下指令:

app.directive('asRelativeRanking', [function() {
    return {
        restrict: 'A',
        require: 'ngModel',
        link: function(scope, element, attrs, ngModel) {
            var relativeRatingOptions = [{
                description: 'Good',
                value: 1
            }, {
                description: 'Better',
                value: 2
            }];

            scope._asRelativeRatingOptions = relativeRatingOptions;

            // ToDo: Set the data-ng-options value a way that lets angular really use it.
            element.attr('data-ng-options', 'relativeRating.description for relativeRating in _asRelativeRatingOptions track by relativeRating.value');

            // format text going to view (model to view)
            ngModel.$formatters.push(function(value) {
                return value == null ? value : relativeRatingOptions.filter(function(relativeRating) {
                    return relativeRating.value === value;
                })[0];
            });

            // format text from view (view to model)
            ngModel.$parsers.push(function(option) {
                return option == null ? option : option.value;
            });
        }
    }
}]);

不幸的是设置element.attr不起作用,所以角度尊重它。在DOM中我可以看到语句,但angular不会处理它。如果我将HTML重写为:

<select as-relative-ranking 
    data-ng-model="myRating"
    data-ng-options='relativeRating.description for relativeRating in _asRelativeRatingOptions track by relativeRating.value'>
</select>

一切正常,但我想从指令中更改ngOptions,以便我的HTML保持干净。

1 个答案:

答案 0 :(得分:0)

<强> HTML

<div ng-controller="Ctrl">
    <div>
        <h2>Without directive</h2>
        <label>Ferries</label>
        <select ng-model="ferry" ng-options="ferry.Id as ferry.Description for ferry in ferries">
            <option style="display: none" value="">-- Choose ferry --</option>
        </select>
        <br/>
        <label>Routes</label>
        <select ng-model="route" ng-options="route.Code as route.Name for route in routes">
            <option style="display: none" value="">-- Choose route --</option>
        </select>
    </div>
    <div>
        <h2>With directive (working now!)</h2>
        <dropdown title="Choose ferry" label="Ferries" array="ferries" opt-value="Id" opt-description="Description"></dropdown>
        <dropdown title="Choose route" label="Routes" array="routes"  opt-value="Code" opt-description="Name"></dropdown>
    </div>

<强> app.js

var app = angular.module('app', []);

function Ctrl($scope){

    $scope.ferries = [
        {Id: 1, Description: "ferry1"}, 
        {Id: 2, Description:"ferry2"}, 
        {Id: 3, Description: "ferry3"}
    ];

    $scope.routes = [
        {Code: "RT1", Name: "route1"}, 
        {Code: "RT2", Name:"route2"}, 
        {Code: "RT2", Name: "route3"}
    ];
}

app.directive('dropdown', function(){
    return {
        restrict: 'E',
        scope: {
            array: '='
        },
        template:   '<label>{{label}}</label>' +
                    '<select ng-model="ngModel" ng-options="a[optValue] as a[optDescription] for a in array">' +
                        '<option style="display: none" value="">-- {{title}} --</option>' +
                    '</select>',
        link: function (scope, element, attrs) {
            scope.label = attrs.label;  
            scope.title = attrs.title;
            scope.optValue = attrs.optValue;
            scope.optDescription = attrs.optDescription;
        }
    };
});

demo click here