2017-03-21 5 views
2

Ich möchte eine Liste von Elementen machen, Doppelklick auf einen Artikel macht es editierbar. Wenn Sie derzeit ein Element bearbeiten, wird durch Klicken außerhalb (z. B. blur) oder durch Eingabe über die Tastatur der neue Wert eingegeben.Setzen Sie den Fokus auf den hinzugefügten Artikel

Jetzt möchte ich ein + Symbol hinzufügen, um ein Element zur Liste hinzuzufügen. Nachdem ich auf das + Symbol geklickt habe, möchte ich, dass der Fokus (und Doppelklick) auf dem hinzugefügten Element liegt, damit wir das direkt bearbeiten können.

Weiß jemand, wie man das erreicht?

JSBin

<!DOCTYPE html> 
<html> 
<head> 
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.7/angular.min.js"></script> 
    <style> 
    input { 
     font-size: 20px; 
     border:none; 
     background-color:transparent; 
    } 
    </style> 
</head> 
<body ng-app="app" ng-controller="Ctrl"> 
    <table> 
    <tr ng-repeat="item in items"> 
     <td> 
     <input type="text" value="{{item.name}}" ng-blur='eEditable = -1' ng-readonly='$index !== eEditable' ng-dblclick="eEditable = $index" ng-keypress="keypress($event)"/> 
     </td> 
    </tr> 
    </table> 
    <div ng-click="add()">+</div> 
    <script> 
    var app = angular.module('app', []); 
    app.controller('Ctrl', ['$scope', function ($scope) { 
     $scope.items = [{ name: "item #1" }, { name: "item #2" }, { name: "item #3" }]; 
     $scope.eEditable = -1; 
     $scope.keypress = function ($event) { 
     if ($event.keyCode === 13) 
      $event.target.blur() 
     } 
     $scope.add = function() { 
     $scope.items.push({name: "new"}); 
     } 
    }]) 
    </script> 
</body> 
</html> 

Antwort

0

Hier ist eine Lösung mit einer benutzerdefinierten Anweisung. (Ich habe gehalten JQuery, weil es zwei nützliche Methoden hat: focus und select)

app.directive("customFocus", function() { 
    return { 
    restrict : "A", 
    link: function(scope, element, attrs) { 
     scope.$watch(attrs.customFocus, function(newValue) { 
     if(newValue) { 
      $(element).focus(); 
      window.setTimeout(function() { $(element).select(); }, 0); 
     } 
     }); 
    } 
} 

Sie jetzt diese Richtlinie als ein Attribut für jedes input Element anwenden kann:

<input 
    type="text" 
    value="{{item.name}}" 
    custom-focus='$index == eEditable' 
    ng-blur='eEditable=-1' 
    ng-readonly='$index !== eEditable' 
    ng-dblclick="eEditable = $index" 
    ng-keypress="keypress($event)"/> 

Die einzige erforderliche Änderung in Ihr Controller ist eEditable, um den endgültigen Index gleich, wenn Sie ein Element hinzugefügt haben:

$scope.add = function() { 
    $scope.items.push({name: "new"}); 
    $scope.eEditable = $scope.items.length-1; 
} 

https://plnkr.co/edit/3bkJa2FcbTm4uSZ95BNi?p=preview

Diese Lösung scheint eleganter zu sein als the pure JQuery solution, denn mit dieser Lösung muss der Controller nichts über die gerenderten DOM-Elemente wissen.

Ein Problem ist, dass es eine Lüge sagen könnte: Wenn es mehr als ein Element mit "custom-focus = 'true'" gibt, haben Sie ein undefiniertes Verhalten in Bezug darauf, welches Element tatsächlich den Fokus erhält.

+0

Warum haben Sie Ihre jquery-Lösung gelöscht? Es funktioniert immer, oder? – SoftTimur

+0

@SoftTimur - Es hat funktioniert, es war einfach nicht besonders elegant. :-) Ich mag das eine mehr, obwohl es ein undefiniertes Verhalten hätte, wenn zwei Elemente gleichzeitig auf "True" gesetzt wären. –

+0

zwei großartige Lösungen ... vielen Dank ... – SoftTimur

1

Wenn ich ein Problem wie dieses in Winkel haben, ist es manchmal einfacher zu jQuery greifen.

$scope.add = function() { 
$scope.items.push({name: "new"}); 
$scope.eEditable = $scope.items.length-1; 
window.setTimeout(function() { 
     $("table tr:last td input").focus(); 
}, 0); 

https://jsbin.com/yegokobuna/edit?html,output

Ich drücke den jQuery-Code in window.setTimeout(..., 0) so dass der Code nach dem Winkelrahmen die HTML-Elemente Rendering abgeschlossen aufgerufen wird.

Dies ist keine großartige Lösung. Es ist schwieriger zu warten, da der Controller-Code nun eine genaue Kenntnis des gerenderten HTML erfordert. Wenn ich zum Beispiel die Ansicht ändern würde, um die Elemente in einer Reihe von div s anstelle von Tabellenzeilen anzuzeigen, dann müsste ich auch den Controller-Code ändern.

Verwandte Themen