11

私は選択置換ディレクティブを作成して、デザインに従って選択を簡単にスタイルアップできるようにしました (つまり、ディレクティブがそれを行います!)。

属性は、配置した場所にトランスクルージョンせずng-transclude、ルート要素に移動するだけであることに気づきませんでした。

ここに例があります: http://plnkr.co/edit/OLLntqMzbGCJS7g7h1j4?p=preview

見栄えが良いことがわかります... しかし、大きな欠点が 1 つあります。および属性は転送されていませんidnameこれnameがないと、サーバーに投稿されません (このフォームは既存のシステムに結び付けられるため、モデルの AJAX 処理はオプションではありません)。

たとえば、これは私が始めるものです:

<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、選択に属性がないため、実際にはデータがサーバーに送信されないという問題があります。

明らかに、プリコンパイル フェーズを使用してnameおよびid属性を転送できますが (これが現在行っていることです)、すべての属性を自動的に転送して、任意のクラス、任意のデータ、 (ng-)required、(ng-)disabled 属性など。

作業を開始しようとtransclude: 'element'しましたが、テンプレートから他の属性をテンプレートに追加できませんでした。

注: ここで投稿を見ました: How can I transclude into an attribute? 、しかし、データを手動で転送しているように見えます。すべての属性を自動転送することを目指しています。

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() || '';
    }
};
}]);

2 番目のアプローチ: デモでは、リンク メソッドの最後に次の行を含めるだけです。

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