0

我正在创建一个精美的滑块,允许用户在一个范围内选择一个值,并且我正在尝试将其构建为 AngularJS 指令。范围中的每个步骤都有一个简短的文本描述,显示在该位置。例如:

 Temperature
                  Warm
[------------------^------]
 |     |     |     |     |
 Cold                  Hot

我想在页面上使用这个初始标记,因为它是语义的并且可以优雅地降级:

<div class="prompt scale">
    <label for="mySelect">Temperature</label>
    <select name="mySelect">
        <option value="1">Cold</option>
        <option value="2">Cool</option>
        <option value="3">Neutral</option>
        <option value="4">Warm</option>
        <option value="5">Hot</option>
    </select>
</div>

然后我会用精美的滑块标记完全替换它。但是,这样做需要 Angular 能够读取原始标记,以便提取渲染精美滑块所需的数据(每个选项的值和标签)。但是,我找不到任何可以引用原始元素及其子元素的地方。声明指令时,compile() 和 link() 函数都引用模板元素,而不是原始元素。如何阅读原始标记,包括访问其后代?

4

1 回答 1

2

如果您要在指令配置对象上使用模板属性,我猜您将失去查看原始文件的能力。

我认为要有效地做你正在做的事情,你需要使用我不精通的编译指令函数。我没有使用它来向你展示这个:

http://jsfiddle.net/2TPWA/

基本上为每个重要的数据创建指令。让他们共享一个控制器来注册所有这些数据。通过这样做,父指令可以使其子指令不一定是它的指定深度。隐藏(或删除,如果您愿意)原始标记,然后根据合并信息创建您的小部件。

在您的情况下,我会像您在此处看到的那样创建用于连接所有内容的指令,以及另一个指令,该指令本身就是小部件,可以使用属性或配置对象(如另一个回答者建议的那样)创建。

<div>
<div sliding-scale class="prompt scale">
<label sliding-scale-title for="mySelect">Temperature</label>
<select name="mySelect">
    <option sliding-scale-option value="1">Cold</option>
    <option sliding-scale-option value="2">Cool</option>
    <option sliding-scale-option value="3">Neutral</option>
    <option sliding-scale-option value="4">Warm</option>
    <option sliding-scale-option value="5">Hot</option>
</select>
</div>
</div>



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

myApp.directive('slidingScaleTitle', function () {
    return {
        require: '^slidingScale',
        link: function (scope, element, attrs, controller) {
            controller.setTitle(element.text());
        }
    };
});

myApp.directive('slidingScaleOption', function () {
    return {
        require: '^slidingScale',
        link: function (scope, element, attrs, controller) {
            controller.addOption({ 
                value: attrs.value,
                text: element.text()
            });
        }
    };
});

myApp.directive('slidingScale', function ($compile) {
    var template = '<div><b>{{ title }}</b><ul><li ng-repeat="o in options"><b>{{ o.value }}:</b> {{ o.text }} </li></ul>';

    return {
        // You should make this its own controller if you want this unit-tested.
        // I'm inlining it as an example.
        controller: function ($scope) {
            var title;
            var options = [];

            this.setTitle = function (value) {
                title = value;
            };
            this.getTitle = function () {
                return title;
            };
            this.getOptions = function () {
                return options;
            }
            this.addOption = function (value) {
                options.push(value);
            };
        },
        link: function (scope, element, attrs, controller) {

            scope.$watch(controller.getTitle, function (value) {
                scope.title = value;
            });

            scope.$watch(controller.getOptions, function (value) {
                scope.options = value;
            });

            element.children().css('display', 'none');
            fancySliderElement = angular.element(template);
            element.append(fancySliderElement);
            $compile(fancySliderElement)(scope);
        }
    }
});
于 2013-08-29T07:22:23.033 回答