2012-12-28 20 views
15

Czy istnieje wyraźniejszy sposób delegowania fokusu do elementu po kliknięciu pola wyboru. Tutaj jest brudna wersja I hacked:AngularJS - Ogniskowanie elementu wejściowego po kliknięciu pola wyboru

HTML

<div ng-controller="MyCtrl"> 
    <input type="checkbox" ng-change="toggled()"> 
    <input id="name"> 
</div> 

JavaScript

var myApp = angular.module('myApp',[]); 

function MyCtrl($scope, $timeout) { 
    $scope.value = "Something"; 
    $scope.toggled = function() { 
     console.debug('toggled'); 
     $timeout(function() { 
      $('#name').focus(); 
     }, 100); 
    } 
} 

JSFiddle: http://jsfiddle.net/U4jvE/8/

+0

Powinna również działać wartość opóźnienia 0 (zamiast 100). –

Odpowiedz

17

jak o tym? plunker

$scope.$watch('isChecked', function(newV){ 
     newV && $('#name').focus(); 
    },true); 

@gasgoth i @Mark Rajcok są poprawne. Powinniśmy użyć dyrektywy. Byłem po prostu leniwy.

Oto wersja dyrektywy. plunker Myślę, że jednym dobrym powodem, aby zrobić to jako dyrektywę, można ponownie użyć tej rzeczy.

więc w HTML można po prostu przypisać różne czasowniki modalne do różnych zestawów

<input type="checkbox" ng-model="isCheckedN"> 
<input xng-focus='isCheckedN'> 


directive('xngFocus', function() { 
    return function(scope, element, attrs) { 
     scope.$watch(attrs.xngFocus, 
     function (newValue) { 
      newValue && element.focus(); 
     },true); 
     };  
}); 
0

Czystsze sposobem jest użycie dyrektywy wykonać przełącznik:

app.directive('toggle', function() { 
    return { 
     restrict: 'A', 
     scope: { 
     selector: '=' 
     }, 
     link: function(scope, element, attrs) { 
      element.on('change', function() { 
       $(scope.selector).focus(); 
       scope.$apply(); 
      }); 
     } 
    }: 
}); 

HTML będzie sth like :

<input type='checkbox' toggle selector='#name'> 
+0

Co zrobić, jeśli selektor nie jest unikalny na stronie? W tym przypadku miałbym wiele '.name', ale tylko jeden z nich pasuje do bieżącego zakresu. – kolrie

7

Inna implementacja dyrektywy (która nie wymaga jQuery) i pożyczanie niektóre z kodem @ maxisam za:

myApp.directive('focus', function() { 
    return function(scope, element) { 
     scope.$watch('focusCheckbox', 
     function (newValue) { 
      newValue && element[0].focus() 
     }) 
    }  
}); 

HTML:

<input type="checkbox" ng-model="focusCheckbox"> 
<input ng-model="name" focus> 

Fiddle.

Ponieważ ta dyrektywa nie tworzy zakresu izolowania (lub zakresu podrzędnego), dyrektywa przyjmuje, że zakres ma zdefiniowaną właściwość focusCheckbox.

+0

@maxisam, podoba mi się atrybut dodany w Twojej odpowiedzi. BTW, czy element.focus() działa dla ciebie? Musiałem użyć elementu [0] .focus(). –

+0

Zapomniałem, że włączasz jQuery, dlatego właśnie działa element.focus(). Jeśli jQuery nie jest dołączony, musimy użyć elementu [0] .focus(). –

5

Jeśli chcesz uczynić go bardziej interesujące, a także wsparcie dla dowolnego wyrażenia być oceniane (i nie tylko zmienne), można to zrobić:

app.directive('autofocusWhen', function ($timeout) { 
    return { 
     link: function(scope, element, attrs) { 
      scope.$watch(attrs.autofocusWhen, function(newValue){ 
       if (newValue) { 
        $timeout(function(){ 
         element.focus(); 
        }); 
       } 
      }); 
     } 
    }; 
}); 

A twój html może być trochę bardziej oddzielone, podobnie jak to:

<input type="checkbox" ng-model="product.selected" /> 
{{product.description}} 
<input type="text" autofocus-when="product.selected" /> 
+1

Dlaczego korzystasz z usługi $ timeout? – Alpha

+1

@Alpha, z jakiegoś powodu, w AngularJS, wyrażenia '$ watch' zdarzają się przed ponownym rysowaniem html, więc natychmiastowe wywołanie do' elementu.focus(); 'skupiłby element i natychmiast tracił ostrość, jako zmiana zakresu, a element został przerysowany. Używanie usługi '$ timeout' jest znanym obejściem dodawania zmiany w kolejce, więc dzieje się to zaraz po odświeżeniu HTML. – ViniciusPires

+1

to działało jak czar –

Powiązane problemy