11

我正在创建一个选择替换指令,以便根据设计轻松设置选择样式,而不必总是正确地标记一堆标记(即指令为您完成它!)。

我没有意识到属性不会嵌入到您放置的位置ng-transclude,而只是转到根元素。

我在这里有一个例子:http: //plnkr.co/edit/OLLntqMzbGCJS7g7h1j4 ?p=preview

你可以看到它看起来很棒......但是有一个主要缺陷。和属性没有被转移idname哪一个,你知道,没有name,它不会发布到服务器(此表单与现有系统相关联,因此不能选择 AJAXing 模型)。

例如,这是我开始的:

<select class="my-select irrelevant-class" name="reason" id="reason" data-anything="banana">
    <option value="">Reason for Contact...</option>
    <option>Banana</option>
    <option>Pizza</option>
    <option>The good stuff</option>
    <option>This is an example of a really, really, really, really, really, really long option item</option>
</select>

...这就是我想要的样子:

<div class="faux-select" ng-class="{ placeholder: default == viewVal, focus: obj.focus }">
    <span class="faux-value">{{viewVal}}</span>
    <span class="icon-arrow-down"></span>
    <select ng-model="val" ng-focus="obj.focus = true" ng-blur="obj.focus = false" ng-transclude class="my-select irrelevant-class" name="reason" id="reason" data-anything="banana">
        <option value="">Reason for Contact...</option>
        <option>Banana</option>
        <option>Pizza</option>
        <option>The good stuff</option>
        <option>This is an example of a really, really, really, really, really, really long option item</option>
    </select>
</div>

...但这就是实际发生的情况:

<div class="faux-select my-select irrelevant-class" ng-class="{ placeholder: default == viewVal, focus: obj.focus }" name="reason" id="reason" data-anything="banana">
    <span class="faux-value">{{viewVal}}</span>
    <span class="icon-arrow-down"></span>
    <select ng-model="val" ng-focus="obj.focus = true" ng-blur="obj.focus = false" ng-transclude>
        <option value="">Reason for Contact...</option>
        <option>Banana</option>
        <option>Pizza</option>
        <option>The good stuff</option>
        <option>This is an example of a really, really, really, really, really, really long option item</option>
    </select>
</div>

具体来说,问题在于选择上没有name属性,因此它实际上并没有将数据发送到服务器。

显然,我可以使用预编译阶段来传输nameid属性(这就是我现在正在做的事情),但是如果它只是自动传输所有属性以便他们可以添加任何类、任意数据、 (ng-)required,(ng-)disabled 属性等。

我试着transclude: 'element'开始工作,但后来我无法将模板中的其他属性添加到它上面。

请注意,我在这里看到了帖子:如何转换为属性?,但看起来他们只是手动传输数据,我的目标是让它自动传输所有属性。

4

2 回答 2

5

您可以使用 compile 函数来访问元素的属性并构建模板。

app.directive('mySelect', [function () {
  return {
    transclude: true,
    scope: true,
    restrict: 'C',
    compile: function (element, attrs) {
        var template = '<div class="faux-select" ng-class="{ placeholder: default == viewVal, focus: obj.focus }">' +
                       '<span class="faux-value">{{viewVal}}</span>' +
                       '<span class="icon-arrow-down entypo-down-open-mini"></span>' +
                       '<select id="' + attrs.id + '" name="' + attrs.name  + '" ng-model="val" ng-focus="obj.focus = true" ng-blur="obj.focus = false" ng-transclude>';
                       '</select>' +
                     '</div>';
        element.replaceWith(template);

        //return the postLink function 
        return function postLink(scope, elem, attrs) {
          var $select = elem.find('select');
          scope.default = scope.viewVal = elem.find('option')[0].innerHTML;

          scope.$watch('val', function(val) {
              if(val === '') scope.viewVal = scope.default;
              else scope.viewVal = val;
          });

          if(!scope.val) scope.val = $select.find('option[selected]').val() || '';
        }
     }
  };
}]);

compile 函数返回 postLink 函数,还有其他方法可以做到这一点,您可以在此处找到更多信息。

这是一个笨蛋

于 2013-11-26T16:39:19.153 回答
0

ng-transclude包含放置指令的元素的内容。我会将该属性分配给其父 div 并将整个选择框嵌入模板中:

第一种方法:

http://plnkr.co/edit/fEaJXh?p=preview

  <div class="form-control my-select">
    <select class="irrelevant-class" name="reason" id="reason" data-anything="banana">
      <option value="">Reason for Contact...</option>
      <option>Banana</option>
      <option>Pizza</option>
      <option>The good stuff</option>
      <option>This is an example of a really, really, really, really, really, really long option item</option>
    </select>
  </div>

并从定义中删除替换选项:

app.directive('mySelect', [function () {
return {
    template: 
        '<div class="faux-select" ng-class="{ placeholder: default == viewVal, focus: obj.focus }">' +
            '<span class="faux-value">{{viewVal}}</span>' +
            '<span class="icon-arrow-down entypo-down-open-mini"></span>' +
            '<div ng-transclude></div>' +
        '</div>',
    transclude: true,
    //replace: true,
    scope: true,
    restrict: 'C',
    link: function (scope, elem, attrs) {
        var $select = elem.find('select');
        scope.default = scope.viewVal = elem.find('option')[0].innerHTML;

        scope.$watch('val', function(val) {
            if(val === '') scope.viewVal = scope.default;
            else scope.viewVal = val;
        });

        if(!scope.val) scope.val = $select.find('option[selected]').val() || '';
    }
};
}]);

第二种方法: 在您的演示中,只需在链接方法的末尾包含以下行:

$select.attr({'id': elem.attr('id'), 'name': elem.attr('name')});
于 2013-11-26T16:49:59.757 回答