AngularJS指令 - 动态输入名称绑定

时间:2014-01-24 03:01:11

标签: javascript angularjs angularjs-directive

我正在尝试更多地了解AngularJS的指令,并遇到了这种情况。我想制作一个可以重复使用的无 - 无线电控制。我已经完成了大部分工作 - 我认为 - 但需要向正确的方向努力。

我有这个指令:

app
  .directive('yesno', function () {
    'use strict';

    var config;

    config = {
      replace: true,
      require: 'ngModel',
      restrict: 'E',
      scope: {
        field: '=',
        model: '='
      },
      templateUrl: 'views/yesno.html'
    };

    return config;
  });

...模板看起来像这样:

<fieldset class="yesno">
  <input id="{{field}}-yes" name="{{field}}" ng-model="model" type="radio" value="yes" />
  <label for="{{field}}-yes">Yes</label>
  <input id="{{field}}-no" name="{{field}}" ng-model="model" type="radio" value="no" />
  <label for="{{field}}-no">No</label>
</fieldset>

......我正在使用它(简化):

<form name="person">
  <yesno field="'happy'" model="happy" />
</form>

不幸的是,我在person对象中获得的属性是{{field}},而不是我想要的happy。我一直告诉自己,我正在尝试的东西是可能的,我只需要找到它;但是什么。

请帮助。

更新

谢谢你,@ HackedByChinese虽然帮助了一点,但仍然没有。问题是我确实想要双向绑定,以便将无线电的值填充到父范围中;相反,当我检查person对象时,它具有{{field}}属性而不是happy属性。

我认为这只是AngularJS不支持的内容:

AngularJS: Fields added dynamically are not registered on FormController

...和

https://github.com/angular/angular.js/issues/1404

2 个答案:

答案 0 :(得分:3)

如果您只是希望field包含输入的字符串值,您可以使用该属性的@前缀来指示它是文本绑定(它将解释该值的值)属性为文字文本)。

  scope: {
    field: '@',
    model: '='
  },

Click for demo

另一方面,如果您需要field绑定到提供给属性的表达式的值(例如,您想绑定到父作用域上的属性),那么您需要更改模板HTML用于评估field(只是{{field()}}),因为它们将是函数。这里的区别在于,如果人们想要直接提供字符串值,他们需要像原始示例一样将其放在引号中。我还建议使用单向绑定,因为您的指令似乎不太可能想要修改父作用域值,因为它只是一个名称。使用&前缀。

  scope: {
    field: '&',
    model: '='
  },

<fieldset class="yesno">
  <input id="{{field()}}-yes" name="{{field()}}" ng-model="model" type="radio" value="yes" />
  <label for="{{field()}}-yes">Yes</label>
  <input id="{{field()}}-no" name="{{field()}}" ng-model="model" type="radio" value="no" />
  <label for="{{field()}}-no">No</label>
</fieldset>

Click for second demo.

答案 1 :(得分:0)

我遇到了同样的问题。最简单的解决方案是将名称值直接注入模板字符串。

只要你不需要绑定名称值(即它在指令的生命周期内不需要改变),它就可以工作。考虑到通常使用name属性的方式,我认为这个约束不是问题。

app
  .directive('yesno', function () {
    return {
      replace: true,
      restrict: 'E',
      scope: {
        field: '@',
        model: '='
      },
      template: function(element, attrs) {
        return '<fieldset class="yesno"> \
          <input id="{{field}}-yes" name="{{field}}" ng-model="model" type="radio" value="yes" /> \
           <label for="{{field}}-yes">Yes</label> \
           <input id="{{field}}-no" name="{{field}}" ng-model="model" type="radio" value="no" /> \
           <label for="{{field}}-no">No</label> \
           </fieldset>'.replace('{{field}}', attrs.field, 'g');
      }
    };
});

由于内联html,这个解决方案有点乱。如果要像原始问题一样从文件加载模板,可以这样做:

app
  .directive('yesno', ['$http', '$templateCache', '$compile',
  function ($http, $templateCache, $compile) {
    return {
      restrict: 'E',
      scope: {
        field: '@',
        model: '='
      },
      link: function(scope, element) {
        $http.get('views/yesno.html', {cache:$templateCache})
          .then(function(response) {
            var content = angular.element(response.data.replace('{{field}}', scope.field, 'g'));
            element.append(content);
            $compile(content)(scope);
          });
      }
    };
}]);