2017-01-12 53 views
1

更新1:正しい実装の基礎を設定する最初のサンプルコードを開発しました。
更新2:作業モデルを開発しました。答えを参照してください。角の編集可能なドロップダウン - 選択された値に基づいて編集可能にする

私はこのライブラリを見つけました:

https://libraries.io/bower/editable-dropdown-angularjs

HTML5のデータリスト機能を使用して編集可能なドロップダウンリストを追加することができました。

ただし、唯一必要な機能は、選択した値が「その他」の場合にのみフィールドを編集可能にすることです。

plunkr.coのサンプルを参照してください。作業は、詳細については、以下のrepository

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

を参照してくださいサンプルコードからデモに基づいてvreated。

選択した値が「その他」の場合にのみ、ドロップダウンフィールドを編集可能にすることをお勧めします。

HTML5:

<div ng-app="myApp"> 
    <div ng-controller="demo" style="width:300px;position:fixed;top:20px;left:20px">  
     <p>You selected {{selected}}</p> 
     <editable-dropdown options='list' ng-model='selected'></editable-dropdown> 
    </div> 
</div> 

はJavaScript:

angular.module('myApp', ['editableDropdown']) 
.controller('demo', function($scope){ 
    $scope.list = ['one', 'two', 'other'] 
    $scope.selected; 
}); 

私はjsfiddle(based in this answer)を使用して、このサンプルコードを開発することができました:

http://jsfiddle.net/tarekahf/t392djx1/

作ることができます「その他」が選択されている場合に編集可能なドロップダウンリストd。今、私はこのモードをAngularに変換しています。ご提案があれば教えてください。

+0

。あなたはディレクティブを飾ることができますが、ソースに基づいて自分自身を書く方が良いでしょうか? –

+0

@MikkoViitala:説明を更新しました。私は方法を見つけたと思う。 – tarekahf

答えて

3

あなたの質問にあまり注意を向けていないようですが、私がコメントしたように、あなたのニーズに応じてeditable-dropdown-angularを強制しようとするのではなく、自分の実装を書く方が良いでしょう。

とにかく、私は自分自身のeditable-selectディレクティブを書く自由を取った。

ディレクティブはoptionsの配列から選択し、オプションのother文字列を取ります。これはユーザーが編集可能な選択のデフォルト値です。 optionsから選択すると編集が無効になりますが、otherは自由に変更できます。

あなたは役に立つと思っています。

のApp HTMLテンプレート

<body ng-controller="Ctrl as vm"> 
    <!-- directive --> 
    <editable-select 
    ng-model="vm.selected" 
    options="vm.options" 
    other="Other"> <!-- write "other" here or assign var in controller --> 
    </editable-select> 

    <hr> 
    <span>User selected: {{ vm.selected }}</span> 
</body> 

アプリケーションのJavaScript

angular 
.module('app', [])  
.controller('Ctrl', function() { 
    var vm = this; 
    vm.options = ['One', 'Two']; // selection options 
})  
.directive('editableSelect', function() { 
    return { 
    restrict: 'E', 
    require: '^ngModel', 
    scope: { 
     ngModel: '=', 
     options: '=', 
     other: '@' 
    }, 
    replace: true, 
    templateUrl: 'editable-select-tpl.html', 
    link: function(scope, element) { 
     scope.isDisabled = true; 

     // option clicked handler  
     scope.click = function(option) { 
     scope.ngModel = option; 
     scope.isDisabled = !scope.other || scope.other !== option; 
     if (!scope.isDisabled) { 
      element[0].querySelector('.editable-select').focus(); 
     } 
     }; 

     // option typed handler   
     var unwatch = scope.$watch('ngModel', function(val) { 
     if (!scope.isDisabled) { 
      scope.other = scope.ngModel; 
     } 
     }); 

     // release watcher   
     scope.$on('$destroy', unwatch); 
    } 
    }; 
}); 

指令HTMLテンプレート(編集可能な選択-TPL。htmlの)ここで

<div> 
    <div class="input-group dropdown"> 
    <input name="editable-select" 
      type="text" 
      class="form-control dropdown-toggle editable-select" 
      ng-disabled="isDisabled" 
      ng-model="ngModel"> 
    <ul class="dropdown-menu"> 
     <li ng-repeat="option in options" 
      ng-bind="::option" 
      ng-click="click(option)"> 
     </li> 
     <li ng-if="other" role="presentation" class="divider"></li> 
     <li ng-if="other" ng-bind="other" ng-click="click(other)"></li> 
    </ul> 
    <span class="input-group-addon dropdown-toggle" data-toggle="dropdown"> 
     <span class="caret"></span> 
    </span> 
    </div> 
    <span class="small text-muted" ng-show="!isDisabled">Type in your selection</span> 
</div> 

CSS

input[name="editable-select"]:disabled { 
    background-color: #ffffff; 
} 

.dropdown-menu:hover { 
    cursor: pointer; 
} 

.dropdown-menu li { 
    padding-left: 10px; 
} 

.dropdown-menu li:hover { 
    background-color: #eeeeee; 
} 

enter image description here

関連plunkerここhttps://plnkr.co/edit/7bVgDW

+0

多くのおかげで答え@Mikko。スケジュール制約のために開発されたソリューションをプッシュしなければならないので、私のケースではうまくいくかどうかを検証する機会はありませんでした。私は解答として(別の選択肢として)私の解答を掲示し、今後のスプリントであなたの解答をチェックするために最善を尽くします。 – tarekahf

+1

勉強するのに十分な時間があった後、私があなたの解決策を理解したことをお知らせします。あなたのソリューションは非常に効率的で、今後の予定では私のプロジェクトで実装する予定です。オプションの 'value'とオプション' text'を標準のドロップダウンリストと同じようにすることだけが必要です。私はあなたのソリューションにこの機能を追加する方法を知っていると思います。 – tarekahf

0

は私のソリューションです。これは別の投稿に基づいていますが、ソースを覚えていません。助けてくれたすべての人に感謝します。

editable-dropdownという要素をselect要素に追加するだけです。属性の値は、input要素のIDである必要があります。

スタイル:

.stop-wrap { 
    display: inline-block; 
} 

.select-editable { 
    position:relative; 
    background-color:white; 
    border:solid grey 1px; 
    width:120px; 
    height:25px; 
    vertical-align: middle; 
    margin-bottom: 5px; 
} 
.select-editable select { 
    position:absolute; 
    top:0px; 
    left:0px; 
    border:none; 
    width:118px; 
    margin:0; 
} 
.select-editable input { 
    position:absolute; 
    top:0px; 
    left:0px; 
    width:100px; 
    padding:1px; 
    border:none; 
} 
.select-editable select:focus, .select-editable input:focus { 
    outline:none; 
} 

HTML:

<div class="select-editable stop-wrap"> 
    <select editable-dropdown="input_elem" id="input_elem_sel" name="input_elem_sel"> 
      <option value=""></option> 
      <option value="Option 1">Option 1</option> 
      <option value="Option 2">Option 2</option> 
      <option value="Option 3">Option 3</option> 
      <option value="Option 4">Option 4</option> 
      <option value="Other">Other ...</option> 
    </select> 
    <input id="input_elem" name="input_elem" ng-model="input_elem" force-model-update> 
</div> 

はJavaScript:それを行うにはオプションはありませんソースを見てみると

//This uses two fields, SELECT and INPUT. The input element is identfied by the attribute 'editableDropdown' 
app.directive('editableDropdown', function(){ 
    return { 
     link: function (scope, elemSel, attrs) { 
      //debugger; 
      var inpElemID = attrs.editableDropdown; 
      var inpElem; 
      //The parameter 'elemSel' is the SELECT field 
      function initInpElem() { 
       if ($(elemSel).is("select")) { 
        inpElem = $('#' + inpElemID); 
       } else { 
        //This is in case the Dropdown is based on DATALIST which is not yet implemented 
        //In this case, the input element is actually the same as the dropdown field using DATALIST 
        inpElem = elemSel; 
       } 
      } 
      function updateEditable(elm) { 
       initInpElem(); 
       //Copy value from SELECT element to the INPUT Element 
       //Use NgModelController to copy value in order to trigger validation for 'inpElem' 
       var selectedValue = $(elm).children("option").filter(":selected").text(); 
       //or var selectedValue = elm.val(); 
       //TODO: will have to add more control here since the SELECT value and text are not the same 
       //  Might cause some issue while rendering value in PDF. 
       angular.element(inpElem).controller('ngModel').$setViewValue(elm.val()); 
       angular.element(inpElem).controller('ngModel').$render(); 
       makeEditable(elm); 
      } 
      function makeEditable(selElm) { 
       //debugger; 
       initInpElem(); 
       if ($(selElm).is("select")) { 
        if (selElm.val() == "Other") { 
          $(inpElem).prop("readonly", false); 
        } else { 
          $(inpElem).prop("readonly", true); 
        } 
       } else { 
        //This part is not yet implemented. It is to be completed and verified in case the dropdown is `datalist`. You can skip this part. 
        if (elm.value != "Other" && !$(elm).attr("keypressOff")) { 
         $(elm).keypress(function(event) { 
          console.log("keypress preventd") 
          event.preventDefault(); 
         }) 
        } else { 
         $(elm).off("keypress"); 
         $(elm).attr("keypressOff", true); 
         console.log("keypress event removed") 
        } 
       } 
      }   
      angular.element(document).ready(function(){ 
       makeEditable(elemSel); 
      }); 
      $(elemSel).change(function() { 
       updateEditable(elemSel); 
      }); 
     } 
    } 
}); 
+0

あなたはスプリントをやっているなら、リファクタリングに精通しています:)この場合、このソリューションは機能しますが、角度やハードコーディングされた「その他」や必須IDを使用するときは、jquery関連のものをすべて取り除きたいと思うでしょう。 –

+0

@MikkoViitala、それを行う方法のサンプルで改良すべき正確な部分を指摘することによって私を助けることは素晴らしいことでしょう。たとえば、Angular内でjQueryを100%取り除くことはほぼ不可能であることを理解しています。私は来るべきスプリントでそのような改善を予定します。 – tarekahf

+0

私は答えを投稿しました:あなたは正しい方向を指すべきです。あなたがそれを逃したならPlunkrへのリンクもあります。とにかく、あなたができるなら、指示(分離)した 'scope'を使って指示に必要なものを渡してください。角形アプリケーションのどの部分でも '$'を使うなら、リファクタリングする必要があります。 –

関連する問題