2017-01-12 3 views
1

UPDATE 1: Entwicklung des ersten Beispielcodes als Grundlage für die korrekte Implementierung.
UPDATE 2: ein Arbeitsmodell entwickelt. Siehe Antworten.Editierbare Dropdown-Liste - bearbeitbar basierend auf dem ausgewählten Wert

fand ich diese Bibliothek:

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

die Datalist-Funktion mit HTML5 editierbare Dropdown-Liste ermöglicht das Hinzufügen.

Es funktioniert gut, die einzige erforderliche Funktion ist jedoch, das Feld nur dann editierbar zu machen, wenn der ausgewählte Wert "Andere" ist.

Siehe Beispiel in plunkr.co Arbeits vreated vom repository auf der Demo basiert

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

Siehe Beispielcode unten.

Schätzen Sie Ihre Vorschläge, damit das Dropdown-Feld nur bearbeitet werden kann, wenn der ausgewählte Wert "Andere" lautet.

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; 
}); 

konnte ich diesen Beispielcode verwenden jsfiddle entwickeln (based in this answer):

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

Welche der Herstellung ermöglicht Dropdown-Liste editierbar, wenn "Andere" ausgewählt ist d. Jetzt wandle ich diesen Modus in den Winkelmodus um. Wenn Sie einen Vorschlag haben, lassen Sie es mich bitte wissen.

+0

an der Quelle der Suche gibt es keine Möglichkeit, das zu tun. Du könntest Direktiven schmücken, aber vielleicht schreibst Du lieber Deine eigenen basierend auf der Quelle? –

+0

@MikkoViitala: Ich habe die Beschreibung aktualisiert. Ich glaube, ich habe einen Weg gefunden. – tarekahf

Antwort

3

Scheint, wie Sie nicht zu viel Aufmerksamkeit auf Ihre Frage zu gewinnen und als ich bemerkte, würden Sie (noch) besser dran, eine eigene Implementierung zu schreiben, anstatt zu versuchen editable-dropdown-angular auf Ihre Bedürfnisse zu erzwingen.

Wie auch immer, ich nahm mir die Freiheit, meine eigene editable-select Richtlinie für Sie zu schreiben.

Direktive nimmt Array von options zur Auswahl und optional other Zeichenfolge, die den Standardwert für benutzerdefinierbare Auswahl ist. Die Bearbeitung ist bei der Auswahl von options deaktiviert, während other kann frei geändert werden.

Ich hoffe, Sie finden es nützlich.

App HTML-Vorlage

<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); 
    } 
    }; 
}); 

Richtlinie HTML-Vorlage (editierbare-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

Verwandte Plunker hier https://plnkr.co/edit/7bVgDW

+0

Vielen Dank @Mikko für die Antwort. Ich hatte nicht die Möglichkeit zu überprüfen, ob es für meinen Fall funktioniert, da ich die entwickelte Lösung aufgrund von Terminplanungsbeschränkungen pushen musste. Ich werde meine Lösung als Antwort (als weitere Option) veröffentlichen und werde mein Bestes geben, um Ihre Lösung in den kommenden Sprints zu überprüfen. – tarekahf

+1

Nur um Sie wissen zu lassen, dass ich Ihre Lösung jetzt verstanden habe, nachdem ich genug Zeit hatte, um sie zu studieren. Ihre Lösung ist sehr effizient und ich werde es in den kommenden Sprints in meinem Projekt umsetzen. Wahrscheinlich ist die einzige Modifikation, die erforderlich ist, die Option "Wert" und die Option "Text" wie die Standard-Dropdown-Liste zu berücksichtigen. Ich denke, ich weiß, wie Sie diese Funktion zu Ihrer Lösung hinzufügen können. – tarekahf

0

Hier ist meine Lösung. Dies basiert auf einem anderen Beitrag, aber ich kann mich nicht an die Quelle erinnern. Danke an alle die geholfen haben.

Fügen Sie einfach das Attribut editable-dropdown gegen das select Element hinzu. Der Wert des Attributs muss die ID des Elements input sein.

Stil:

.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

Wenn Sie Sprints machen, dann sind Sie mit ständigem Refactoring vertraut :) In diesem Fall sollten Sie, solange diese Lösung funktioniert, alle jquery-bezogenen Sachen loswerden, wenn Sie eckige und hartcodierte "Andere" und obligatorische IDs verwenden. –

+0

@MikkoViitala, wäre es toll, mir zu helfen, indem Sie auf die genauen Teile zeigen, die mit Proben verbessert werden, wie man es macht. Zum Beispiel verstehe ich, dass es nahezu unmöglich ist, jQuery 100% innerhalb von Angular loszuwerden. Ich werde solche Verbesserungen in den kommenden Sprints einplanen. – tarekahf

+0

Ich habe eine Antwort geschrieben :), die Sie in die richtige Richtung zeigen sollte. Es gibt auch einen Link zu Plunkr, falls du es verpasst hast. Überlassen Sie alles, was Sie in Ihrer Richtlinie benötigen, über einen (isolierten) "Anwendungsbereich", wenn Sie können. Wenn Sie '$' in irgendeinem Teil Ihrer eckigen Anwendung verwenden, müssen Sie einen Refactor erstellen. –

Verwandte Themen