如何从自定义指令中的ng-options中获取已编译的数组?

scn*_*iro 4 html javascript angularjs angularjs-directive angularjs-ng-options

我有一个自定义指令,我正在<select ng-options="">用这样的装饰......

<select custom ng-model="selected" ng-options="o for o in values">
Run Code Online (Sandbox Code Playgroud)

custom我的指令,并values成为一个简单的数组.这是我的实施......

<select custom ng-model="selected" ng-options="o for o in values">
    <option value selected>uhh?</option>
</select>
Run Code Online (Sandbox Code Playgroud)
app.directive('custom', [function() {
    return {
        scope: {},
        link: function(scope, elem, attrs) {
            // how can I get my array of values here?
        }
    }
}])
app.controller('ctrl', ['$scope', function($scope) {
    $scope.values = ['er', 'um', 'eh'];
}])
Run Code Online (Sandbox Code Playgroud)

link我可以在其中看到它

console.log(attrs.ngOptions);
Run Code Online (Sandbox Code Playgroud)

在这种情况下,退出文字"o for o in values".我可以以某种方式解析或编译我的内容link以获取数组吗?如果我做了类似的事情scope.$parent.values,我发现我可以抓住它,但这似乎是不必要的,我需要知道它的名字"values".我可以通过一些hacky感觉字符串操作来定位它,但我希望有一种更直观的方式.

hacky例如

var array = attrs.ngOptions.split(' ').pop(); // "values"

console.log(scope.$parent[array]);
Run Code Online (Sandbox Code Playgroud)

附注 - 此示例限于AngularJS 1.2.x.

JSFiddle Link - 示例

New*_*Dev 9

从Angular v1.4开始,指令都select没有ngOptions提供API来获取导致<option>s 的项数组,因此我们只留下2个选择 - 1)将values数组显式传递给custom指令作为属性值,或2)派生它来自微语法ng-options.

随着#1 -的方法是直接的.

对于#2 - 我们需要解析微结合,例如用RegExp.这很脆弱,因为微语法可能在将来发生变化.

我们可以使用Angular自己的正则表达式(参见src v1.4.3)来解析这种语法:

var NG_OPTIONS_REGEXP = /^\s*([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+group\s+by\s+([\s\S]+?))?(?:\s+disable\s+when\s+([\s\S]+?))?\s+for\s+(?:([\$\w][\$\w]*)|(?:\(\s*([\$\w][\$\w]*)\s*,\s*([\$\w][\$\w]*)\s*\)))\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?$/;
Run Code Online (Sandbox Code Playgroud)

(第8组匹配项目)

或者,我们可以使它成为一个更简单的正则表达式,甚至可能更稳定,例如:

/^.*\s+in\s+(\S+)[\s\S]*$/
Run Code Online (Sandbox Code Playgroud)

无论如何,该指令看起来如下:

app.directive('custom', function($parse) {
  return {
    scope: {},
    link: function(scope, elem, attrs) {
      var optionsExp = attrs.ngOptions;

      var match = optionsExp.match(NG_OPTIONS_REGEXP);

      var valuesExp = match[8];

      var valuesFn = $parse(valuesExp);

      var values = valuesFn(scope.$parent);

      // or simpler: 
      // var values = $parse(match[8])(scope.$parent);
    }
  }
})
Run Code Online (Sandbox Code Playgroud)