2017-01-12 5 views
1

ОБНОВЛЕНИЕ 1: разработал первый примерный код, чтобы установить основу для правильной реализации.
ОБНОВЛЕНИЕ 2: разработана рабочая модель. Посмотри ответы.Угловое редактируемое выпадающее меню - сделать редактируемым на основе выбранного значения

Я нашел эту библиотеку:

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

, который позволяет добавлять редактируемый раскрывающийся список с помощью HTML5 DataList функции.

Он работает нормально, однако единственная необходимая функция - сделать редактируемое поле, только если выбранное значение «Другое».

См работает образец в plunkr.co vreated на основе демо от repository

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

Смотрите пример кода ниже для деталей.

Оцените свои предложения, чтобы изменить поле выпадающего меню, только если выбранное значение «Другое».

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/

который позволит сделать выпадающий список доступен для редактирования, если выбрано «Другое» д. Теперь я преобразовываю этот режим в угловой. Если у вас есть какие-либо предложения, пожалуйста, дайте мне знать.

+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> 

App 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 шаблона (редактируемые-Select-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.

Стиль:

.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

Если вы делаете спринты, то вы знакомы с постоянным рефакторингом :) В этом случае, хотя это решение работает, вы хотите избавиться от всех связанных с jquery вещей при использовании угловых, а также жестко закодированных «других» и обязательных идентификаторов. –

+0

@MikkoViitala, было бы здорово помочь мне, указав на точные детали, которые нужно улучшить с образцами о том, как это сделать. Например, я понимаю, что почти невозможно избавиться от jQuery 100% внутри Angular. Я планирую такие улучшения в предстоящих спринтах. – tarekahf

+0

Я отправил ответ :), который должен указать вам в правильном направлении. Там также есть ссылка на Plunkr, если вы его пропустили. В любом случае, передайте все, что вам нужно в вашей директиве, с помощью директивы (изолированной) 'scope', если сможете. Если вы используете '' 'в любой части своего углового приложения, вам нужно реорганизовать. –

Смежные вопросы