带有 <select ng-options> 的指令和间接 [英] Directive with <select ng-options> and indirection

查看:14
本文介绍了带有 <select ng-options> 的指令和间接的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在一个页面上有多个多选,每个都有一些逻辑来填充来自服务器的多选,我想将每个多选包装成一个指令.

在尝试将它们包装到指令中之前,我按如下方式构建了每个:

index.html

 物理构建到模板中,但意识到我必须操纵 DOM 来物理替换 name、ng-model 和ng-选项.这让我想到了 compile 属性,但是 a.) 感觉不对 b.) 设置 <select ng-options="x for x in allgroups"/> 实际上并没有重复它已被插入到 DOM 中.使用 compile 感觉不对;解决这个问题的正确方法是什么?

这是我对指令的第一次尝试,看起来像这样.它并没有真正起作用,而且我认为我的做法是错误的:

index.html

<dimension ng-model="inputs.users" alloptions-model="allusers">Users</dimension>

directives.js

directive('dimension', function() {返回 {限制:'E',范围: {ngModel: '=',alloptionsModel: '='},模板:'

'+'<标签 ng-transclude></label>'+'<字段集>'+'<div class="form-group">'+'<select ng-model="{{ngModel}}" ng-options="x for x in {{alloptionsModel}}" multiple class="form-control"></select>'+'</div>'+'</字段集>'+'</div>',替换:真的,转置:真实};});

很明显,我什至还没有进入服务器负载部分,但我计划将它滚动到指令中的控制器中,并在服务中实际调用 $http.

我觉得我走错了路.如果您对如何重新调整有任何建议,请帮忙!

解决方案

你的指令的主要问题是你不能在 ngModelngOptions 中使用 mustache 绑定指令,因为它们是直接评估的.您可以直接绑定到作用域属性(ngModel 和 alloptionsModel):

directive('dimension', function() {返回 {限制:'E',范围: {ngModel: '=',alloptionsModel: '='},模板:'

'+'<标签 ng-transclude></label>'+'<字段集>'+'<div class="form-group">'+'<select ng-model="ngModel" ng-options="x for x in alloptionsModel" multiple class="form-control"></select>'+'</div>'+'</字段集>'+'</div>',替换:真的,转置:真实};});

请参阅 此 plunkr 以获取工作示例.

编辑至于编译路线,没有错.当您需要动态创建一个模板时它很有用,当您进入 select 的项目模板时,这显然是您的情况.

compile: function(tElement, tAttrs) {var select = tElement.find('select'),值 = tAttrs.value ?'X.'+ tAttrs.value : 'x',标签 = tAttrs.label ?'X.'+ tAttrs.label : 'x',ngOptions = value + ' as ' + label + ' for x in alloptionsModel';select.attr('ng-options', ngOptions);}//在 HTML 文件中<维度 ng-model="inputs.users"alloptions-model="allusers"标签=名称">用户</维度>

我已经使用编译功能更新了 plunkr.

I have several multi-selects on a page, each with a bit of logic that fills that multi-select from the server, and I want to wrap each one up into a Directive.

Before trying to wrap these into Directives, I built each as such:

index.html

<select name="groups" ng-model="inputs.groups" ng-change="groupsChanged()" ng-options="g for g in allgroups" multiple></select>

controllers.js

In the first pass, I do my $http calls from here. Yes, I know, not best practices, but I wanted to prove that this works to myself first.

  $scope.loadSelect = function(_url) {
    $http({
      url: _url,
      method: 'POST',
      data: $scope.inputs,
      model: 'all' + _url
    }).success(function(data, status, headers, config) {
      $scope[config.model] = data;
    });
  };

  // Fill groups
  $scope.loadSelect('groups');

  // When groups change, reload other select fields that depend on groups
  $scope.groupsChanged = function() {
    $scope.loadSelect('categories');
    $scope.loadSelect('actions');
  }

Now I want to migrate this to a Directive. I see two major challenges: 1.) How do I encapsulate the entire set of options (e.g. what is now the "allgroups" model) into the Directive? 2.) Based on initial experiments, I tried to physically build the <select/> into the template, but realized that I have to manipulate the DOM to physically replace name, ng-model, and ng-options. That lead me to the compile attribute, but a.) that feels wrong and b.) setting <select ng-options="x for x in allgroups" /> doesn't actually repeat after it's been inserted into the DOM. Using compile doesn't feel right; what's the right way to approach this?

Here is my first attempt at the Directive looks like this. It doesn't really work, and I think I'm going about it incorrectly:

index.html

<dimension ng-model="inputs.users" alloptions-model="allusers">Users</dimension>

directives.js

directive('dimension', function() {
  return {
    restrict: 'E',
    scope: {
      ngModel: '=',
      alloptionsModel: '='
    },
    template:
        '<div>' + 
          '<label ng-transclude></label>' +
          '<fieldset>' +
              '<div class="form-group">' +
                '<select ng-model="{{ngModel}}" ng-options="x for x in {{alloptionsModel}}" multiple class="form-control"></select>' +
              '</div>' +
           '</fieldset>' +
        '</div>',

    replace: true,
    transclude: true
  };
});

Clearly I haven't even gotten to the server load part yet, but I plan to roll that into a controller in the Directive, with the actual $http call in a service.

I feel like I'm moving down the wrong track. If you have suggestions on how to realign, please help!

解决方案

The main problem with your directive is that you can't use mustache binding in ngModel and ngOptions directive because they are evaluated directly. You can directly bind to the scoped property (ngModel and alloptionsModel):

directive('dimension', function() {
  return {
    restrict: 'E',
    scope: {
      ngModel: '=',
      alloptionsModel: '='
    },
    template:
        '<div>' + 
          '<label ng-transclude></label>' +
          '<fieldset>' +
              '<div class="form-group">' +
                '<select ng-model="ngModel" ng-options="x for x in alloptionsModel" multiple class="form-control"></select>' +
              '</div>' +
           '</fieldset>' +
        '</div>',
    replace: true,
    transclude: true
  };
});

See this plunkr for a working example.

Edit As for the compile route, there is nothing wrong with it. It is useful when you need to dynamically create a template which will clearly be your case when you will get to the select's item template.

compile: function(tElement, tAttrs) {
  var select = tElement.find('select'),
      value = tAttrs.value ? 'x.' + tAttrs.value : 'x',
      label = tAttrs.label ? 'x.' + tAttrs.label : 'x',
      ngOptions = value + ' as ' + label + ' for x in alloptionsModel';

      select.attr('ng-options', ngOptions);
}

// In the HTML file
<dimension ng-model="inputs.users" 
           alloptions-model="allusers"
           label="name">
  Users
</dimension>

I've updated the plunkr with the compile function.

这篇关于带有 &lt;select ng-options&gt; 的指令和间接的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆