指令:如何评估父范围中的ng-options

时间:2013-09-27 17:09:53

标签: angularjs

我正在尝试将select封装在自定义指令中,同时在指令声明中保留ng-options的使用。

目标是能够使用我的指令将ng-options的语法保留在模板中,但要正确地将其转发到指令内部select的ng-options。

更多的话,代码:

指令:

    angular.module('myApp').directive("selectField", function() {
    return {
        restrict: 'EA',
        replace: true,
        transclude : false,
        templateUrl : "/common/tpl/form/select-field.html",
        scope : {
            label   : "@",
            model   : "=",
            options : "&"
        }
    };
});

模板:

<div class="form-group">
    <label for="{{fieldId}}" class="col-lg-2 control-label">{{label | translate}}</label>
    <div class="col-lg-10">
        <select class="form-control" id="{{fieldId}}" ng-model="model" ng-options="{{options}}"></select>
    </div>
</div>

用法:

 <select-field label="myLabel" model="data.mySelectValue" options="p.nom for p in myOptions"></select-field>

而且......错误:

Error: [$parse:syntax] Syntax Error: Token 'for' is an unexpected token at column 7 of the expression [p.nom for p in preteurs] starting at [for p in preteurs].

我尝试选项为“&amp;” ,“=”和“@”属性,但似乎没有任何工作。

使用“=”和“&amp;”,角度会随着给定的错误而爆炸,并且使用“@”属性,表达式将在指令范围内进行评估,但它不起作用,因为“myOptions”不存在于指令自己的范围......

我错过了什么吗?有办法做到这一点吗?

3 个答案:

答案 0 :(得分:1)

没有其他方法可以将选择列表和表达式作为分隔属性... http://blog.benkuhl.com/2013/08/how-to-use-ng-options-in-a-custom-directive-for-a-dropdown/

答案 1 :(得分:1)

我的解决方案依赖于我在angular ng-bind-html and directive within it接受的答案中找到的令人惊讶的编译指令...感谢VKammerrer。这有点笨拙,但看看刚刚发布的博客文章,我认为这可能是一个必要的邪恶。

设置如下:MyCtrl with MyView,其中包含

<select-field compile>

当然,您可以将select-field和compile组合成一个指令。

MyCtrl在范围上定义如下:

$scope.myOptions = [
    { value: 0, nom: 'a' },
    { value: 1, nom: 'b' }
];

MyView具有以下HTML:

<select-field options="myOptions" data="nom" compile></select-field>

selectField的声明如下:

angular.module('myApp')
    .directive('selectField',
        function() {
            return {
                restrict: 'E',
                replace: true,
                transclude: false,
                templateUrl: 'scripts/directives/selectField.tmp.html',
                scope: {
                    options: '=',
                    data: '@'
                }
            };
        }
    );

selectField.tmp.html如下:

<div>
    <select ng-model="something" ng-options="p.{{data}} for p in options"></select>
</div>

好的,这似乎对我有用,如果有帮助/不起作用,请告诉我。

答案 2 :(得分:1)

我找到了另一种不涉及编译的替代方案。

在自定义指令中定义2个绑定:

selectOptions: "<", // One way, it will contain the source array
selectOptionsExp: "@" // Literal string, it will contain the options expression

然后你可以在模板中使用这个html:

<select ng-model="..." ng-options="{{ vm.selectOptionsExp }}"></select>

这就是用法:

<my-directive ng-model="vm.selectedValue"
              select-options="vm.valuesArray"
              select-options-exp="item.label for item in vm.selectOptions track by item.id" />

请注意,“vm.selectOptions”在内部作用域中传递,因此可以使用而无需编译或转换。

此外,您可以使用可替换令牌简化使用,该令牌向读者表明该变量在当前范围中不存在:

vm.getOptionsExp = function() { return vm.selectOptionsExp.replace("$options", "vm.selectOptions"); }
<select ng-model="..." ng-options="{{ vm.getOptionsExp() }}"></select>
<my-directive ng-model="vm.selectedValue"
                  select-options="vm.valuesArray"
                  select-options-exp="item.label for item in $options track by item.id" />

这可以扩展到包括使用单独的选项对自定义函数进行排序/过滤。