- Kiedy modal jest otwarty, ustaw fokus na predefiniowanym <wejściu> wewnątrz tego modalu.
Zdefiniuj dyrektywę i poproś ją o obejrzenie właściwości / wyzwalacza, aby wiedział, kiedy skupić element:
Name: <input type="text" focus-me="shouldBeOpen">
app.directive('focusMe', ['$timeout', '$parse', function ($timeout, $parse) {
return {
//scope: true, // optionally create a child scope
link: function (scope, element, attrs) {
var model = $parse(attrs.focusMe);
scope.$watch(model, function (value) {
console.log('value=', value);
if (value === true) {
$timeout(function () {
element[0].focus();
});
}
});
// to address @blesh's comment, set attribute value to 'false'
// on blur event:
element.bind('blur', function () {
console.log('blur');
scope.$apply(model.assign(scope, false));
});
}
};
}]);
Plunker
Limit czasu $ wydaje się potrzebny, aby dać czas modalny na renderowanie.
„2.” Za każdym razem, gdy <wejście> staje się widoczne (np. Klikając jakiś przycisk), ustaw na nim fokus.
Utwórz dyrektywę zasadniczo podobną do powyższej. Obserwuj jakąś właściwość zakresu, a gdy stanie się prawdą (ustaw ją w module obsługi ng-click), uruchom element[0].focus()
. W zależności od przypadku użycia może być potrzebny limit czasu dla tego:
<button class="btn" ng-click="showForm=true; focusInput=true">show form and
focus input</button>
<div ng-show="showForm">
<input type="text" ng-model="myInput" focus-me="focusInput"> {{ myInput }}
<button class="btn" ng-click="showForm=false">hide form</button>
</div>
app.directive('focusMe', function($timeout) {
return {
link: function(scope, element, attrs) {
scope.$watch(attrs.focusMe, function(value) {
if(value === true) {
console.log('value=',value);
//$timeout(function() {
element[0].focus();
scope[attrs.focusMe] = false;
//});
}
});
}
};
});
Plunker
Aktualizacja 7/2013 : widziałem, jak kilka osób korzysta z moich oryginalnych dyrektyw zakresu izolowania, a następnie mają problemy z osadzonymi polami wejściowymi (tj. Polem wejściowym w module). Dyrektywa bez nowego zakresu (lub ewentualnie nowego zakresu potomnego) powinna złagodzić część bólu. Powyżej zaktualizowałem odpowiedź, aby nie używać zakresów izolowanych. Poniżej znajduje się oryginalna odpowiedź:
Oryginalna odpowiedź na 1., przy użyciu zakresu izolowania:
Name: <input type="text" focus-me="{{shouldBeOpen}}">
app.directive('focusMe', function($timeout) {
return {
scope: { trigger: '@focusMe' },
link: function(scope, element) {
scope.$watch('trigger', function(value) {
if(value === "true") {
$timeout(function() {
element[0].focus();
});
}
});
}
};
});
Plunker .
Oryginalna odpowiedź na 2., przy użyciu zakresu izolowania:
<button class="btn" ng-click="showForm=true; focusInput=true">show form and
focus input</button>
<div ng-show="showForm">
<input type="text" focus-me="focusInput">
<button class="btn" ng-click="showForm=false">hide form</button>
</div>
app.directive('focusMe', function($timeout) {
return {
scope: { trigger: '=focusMe' },
link: function(scope, element) {
scope.$watch('trigger', function(value) {
if(value === true) {
//console.log('trigger',value);
//$timeout(function() {
element[0].focus();
scope.trigger = false;
//});
}
});
}
};
});
Plunker .
Ponieważ musimy zresetować właściwość trigger / focusInput w dyrektywie, „=” jest używane do dwukierunkowego wiązania danych. W pierwszej dyrektywie wystarczyło „@”. Zauważ też, że używając „@” porównujemy wartość wyzwalacza z „true”, ponieważ @ zawsze daje ciąg znaków.
ng-model
w polu wejściowym, wartość modelu zostanie utracona, gdy użyję tej dyrektywy z użyciem zakresu izolowania. Problem nie występuje, jeśli wypróbuję wersję Josha bez zakresu izolowania. Nadal jestem nowicjuszem i chciałbym zrozumieć różnicę. Oto Plunker, który to pokazuje.value != "true"
, jak się wydaje, rozwiązało mój problem.(EDYCJA: Dodałem zaktualizowane rozwiązanie poniżej tego wyjaśnienia)
Mark Rajcok jest mężczyzną ... i jego odpowiedź jest poprawną odpowiedzią, ale
mawadę (przepraszam Mark) ...... Spróbuj użyć wartości logicznej, aby ustawić ostrość na wejściu, a następnie rozmyj wejście, a następnie spróbuj użyć go, aby ponownie ustawić ostrość. Nie będzie działać, chyba że zresetujesz wartość logiczną na false, a następnie $ digest, a następnie zresetujesz ją z powrotem na true. Nawet jeśli użyjesz porównania ciągu w swoim wyrażeniu, będziesz zmuszony zmienić ciąg na coś innego, $ digest, a następnie zmień go z powrotem.(Rozwiązano ten problem za pomocą procedury obsługi zdarzenia rozmycia).Proponuję więc to alternatywne rozwiązanie:
Użyj zdarzenia, zapomnianej funkcji Angulara.
JavaScript w końcu uwielbia wydarzenia. Wydarzenia są z natury luźno powiązane, a co więcej, unikaj dodawania kolejnego $ watch do $ streszczenia.
Więc teraz możesz użyć tego w ten sposób:
a następnie w dowolnym miejscu w Twojej aplikacji ...
To jest niesamowite, ponieważ możesz robić różne rzeczy za pomocą czegoś takiego. Po pierwsze, możesz powiązać się z wydarzeniami, które już istnieją. Po drugie, zacznij robić coś inteligentnego, publikując zdarzenia w różnych częściach aplikacji, które mogą subskrybować inne części aplikacji.
W każdym razie ten rodzaj rzeczy krzyczy do mnie „zdarzenie napędzane”. Myślę, że jako programiści Angulara bardzo ciężko próbujemy wbić kołki w kształcie lunety w otwory o kształcie zdarzenia.
Czy to najlepsze rozwiązanie? Nie wiem. To rozwiązanie.
Zaktualizowane rozwiązanie
Po komentarzu @ ShimonRachlenko poniżej zmieniłem nieco moją metodę robienia tego. Teraz używam kombinacji usługi i dyrektywy, która obsługuje wydarzenie „za kulisami”:
Poza tym jest to ta sama zasada opisana powyżej.
Oto szybkie demo Plunk
Stosowanie
Źródło
źródło
$broadcast
ze$timeout
jeśli chcesz to do pracy na wejściu sterownika. W przeciwnym razie fajne rozwiązanie.Odkryłem, że niektóre inne odpowiedzi są zbyt skomplikowane, gdy naprawdę potrzebujesz tylko tego
użycie jest
Używamy limitu czasu, aby pozwolić renderować rzeczy w dom, nawet jeśli jest to zero, to przynajmniej na to czeka - w ten sposób działa to w modach i tak dalej
źródło
ng-click
: powiedzmy, że kliknięcie przycisku mang-click="showInput = !showInput
na wejściu. Następnie na podstawie rzeczywistych danych wejściowych dodajng-if="showInput"
. Przełączenie przycisku spowoduje ponowne uruchomienie dyrektywy za każdym razem. Miałem z tym problem, ponieważng-show
używałem niewłaściwego podejścia.HTML ma atrybut
autofocus
.http://www.w3schools.com/tags/att_input_autofocus.asp
źródło
Możesz także użyć funkcji jqlite wbudowanej w angular.
angular.element('.selector').trigger('focus');
źródło
Looking up elements via selectors is not supported by jqLite!
Działa to dobrze i pozwala na skupienie kontroli wejścia
Nie jest to jednak czysto kątowy sposób wykonywania zadania, ale składnia jest zgodna ze stylem kątowym. Jquery odgrywa rolę pośrednio i bezpośrednio uzyskuje dostęp do DOM za pomocą Angulara (jQLite => JQuery Light).
W razie potrzeby kod ten można łatwo umieścić w prostej dyrektywie kątowej, w której element jest bezpośrednio dostępny.
źródło
Looking up elements via selectors is not supported by jqLite!
angular.element
staje się to opakowanie$() / jQuery()
. Bez tego to nie zadziała, a i tak po prostu używasz jQuery (ale popraw mnie, jeśli się mylę)Nie sądzę, aby limit czasu $ był dobrym sposobem na skoncentrowanie elementu na tworzeniu. Oto metoda wykorzystująca wbudowaną funkcjonalność kątową, wykopaną z mrocznych głębi dokumentów kątowych. Zwróć uwagę, w jaki sposób atrybut „link” można podzielić na „przed” i „po”, dla funkcji przed i po linku.
Przykład roboczy: http://plnkr.co/edit/Fj59GB
Pełna dokumentacja dyrektywy AngularJS: https://docs.angularjs.org/api/ng/service/$compile
źródło
Oto moje oryginalne rozwiązanie:
plunker
I HTML:
Co to robi:
Skupia wejście, gdy staje się widoczne w ng-show. Nie ma tu możliwości korzystania z $ watch ani $.
źródło
Napisałem dwuznacznie wiążącą dyrektywę fokusową, podobnie jak ostatnio model.
Możesz użyć dyrektywy fokusowej w następujący sposób:
Jeśli wprowadzisz zmienną zakresu FocusVariable
true
w dowolnym miejscu kontrolera, dane wejściowe zostaną zogniskowane. A jeśli chcesz „rozmazać” dane wejściowe, someFocusVariable można ustawić na false. To jak pierwsza odpowiedź Marka Rajcoka, ale z dwukierunkowym wiązaniem.Oto dyrektywa:
Stosowanie:
Oto skrzypce:
http://fiddle.jshell.net/ubenzer/9FSL4/8/
źródło
Dla tych, którzy używają Angulara z wtyczką Bootstrap:
http://angular-ui.github.io/bootstrap/#/modal
Możesz sprawdzić
opened
obietnicę wystąpienia modalnego:źródło
$timeout
z50ms
jest w potrzebie zamiast0
.Uznałem, że użyteczne jest użycie ogólnego wyrażenia. W ten sposób możesz robić rzeczy takie jak automatyczne przesuwanie fokusa, gdy wprowadzony tekst jest prawidłowy
Lub automatycznie ustaw ostrość, gdy użytkownik wypełni pole o stałej długości
I oczywiście ostrość po załadowaniu
Kod dyrektywy:
źródło
Nie wskrzeszać zombie ani nie stosować własnej dyrektywy (ok, właśnie to robię):
https://github.com/hiebj/ng-focus-if
http://plnkr.co/edit/MJS3zRk079Mu72o5A9l6?p=preview
źródło
Po pierwsze, oficjalnym sposobem skoncentrowania się jest na mapie drogowej dla wersji 1.1 . W międzyczasie możesz napisać dyrektywę, aby zaimplementować fokus ustawień.
Po drugie, aby ustawić fokus na elemencie, który stanie się widoczny, obecnie wymaga obejścia. Po prostu opóźnij wywołanie elementu focus () za pomocą
$timeout
.Ponieważ ten sam problem z kontrolerem-modyfikującym-DOM istnieje dla skupienia, rozmycia i wyboru, proponuję mieć
ng-target
dyrektywę:Kątowy wątek tutaj: http://goo.gl/ipsx4 , a więcej szczegółów blogowanych tutaj: http://goo.gl/4rdZa
Poniższa dyrektywa utworzy
.focus()
funkcję w twoim kontrolerze zgodnie z twoimng-target
atrybutem. (Tworzy również.blur()
a.select()
.) Demo: http://jsfiddle.net/bseib/WUcQX/źródło
ngFocus
wydaje się być sposobem obsługifocus
zdarzeń, a nie sposób ustawić ostrość na elemencie.Zamiast tworzyć własną dyrektywę, można po prostu użyć funkcji javascript do osiągnięcia celu.
Oto przykład.
W pliku HTML:
W pliku javascript, na przykład w kontrolerze, w którym chcesz aktywować fokus:
źródło
Jeśli chcesz tylko prostego fokusa, który był kontrolowany przez kliknięcie ng.
HTML:
Dyrektywa:
źródło
Prosty, który działa dobrze z modami:
Przykład
źródło
Możesz po prostu stworzyć dyrektywę, która wymusza skupienie się na dekorowanym elemencie w postLinking:
Następnie w swoim html:
Działa to w przypadku modów i przełączanych elementów ng-if, nie w przypadku ng-show, ponieważ postLinking odbywa się tylko podczas przetwarzania HTML.
źródło
Mark i Blesh mają świetne odpowiedzi; jednak Mark ma wadę, na którą zwraca uwagę Blesh (poza tym, że jest skomplikowany w implementacji), i uważam, że odpowiedź Blesha zawiera błąd semantyczny w tworzeniu usługi, która konkretnie dotyczy wysyłania żądania skupienia do interfejsu, gdy naprawdę wszystko, czego potrzebował, to sposób opóźnić wydarzenie, aż wszystkie dyrektywy będą nasłuchiwać.
Więc oto co skończyłem, co kradnie wiele z odpowiedzi Blesha, ale oddziela semantykę zdarzenia kontrolera i usługi „po załadowaniu”.
Pozwala to na łatwe podpięcie zdarzenia kontrolera do rzeczy innych niż skupienie określonego elementu, a także pozwala na obciążenie funkcji „po załadowaniu” tylko wtedy, gdy jest to potrzebne, co może nie być w wielu przypadkach.
Stosowanie
Źródło
źródło
Jest to również możliwe w użyciu
ngModelController
. Praca z wersją 1.6+ (nie wiem ze starszymi wersjami).HTML
JS
-
NB: W zależności od kontekstu może być konieczne zawinięcie funkcji limitu czasu.
NB²: Przy użyciu
controllerAs
jest to prawie to samo. Wystarczy wymienićname="myForm"
zname="vm.myForm"
i w JS,vm.myForm.myText.$$element.focus();
.źródło
Prawdopodobnie najprostsze rozwiązanie w wieku ES6.
Dodanie jednej dyrektywy liniowej powoduje, że atrybut HTML „autofocus” działa na Angular.js.
Teraz możesz po prostu użyć składni autofocus HTML5, takiej jak:
źródło
.directive('autofocus', ['$timeout', ($timeout) => ({link: (_, e) => $timeout(() => e[0].focus())})])
Jestem tu tylko nowicjuszem, ale dzięki tej dyrektywie mogłem go uruchomić w pliku ui.bootstrap.modal :
i w metodzie $ modal.open użyłem następujących elementów, aby wskazać element, na którym należy ustawić fokus:
na szablonie mam to:
źródło
Poniższa dyrektywa załatwiła sprawę. Użyj tego samego atrybutu HTML autofocus do wprowadzania danych.
źródło
Jeśli używasz modalInstance i masz obiekt, którego możesz użyć „następnie” do wykonania akcji po otwarciu modalu. Jeśli nie używasz modalInstance, a kodowanie jest otwarte, aby otworzyć modal, możesz użyć zdarzenia. Limit czasu $ nie jest dobrym rozwiązaniem.
Możesz zrobić (Bootstrap3):
W modalInstance możesz spojrzeć na bibliotekę, w jaki sposób wykonać kod po otwarciu modalu.
Nie używaj $ timeout w ten sposób, $ timeout może wynosić 0, 1, 10, 30, 50, 200 lub więcej, to zależy od komputera klienckiego i procesu otwierania modalnego.
Nie używaj $ timeout, niech metoda powie ci, kiedy możesz się skupić;)
Mam nadzieję, że to pomoże! :)
źródło
Cała poprzednia odpowiedź nie działa, jeśli żądany element fokusu zostanie wstrzyknięty do szablonu dyrektywy. Poniższa dyrektywa pasuje zarówno do elementu prostego, jak i do elementu wprowadzonego przez dyrektywę (napisałem go na maszynie ). akceptuje selektor dla wewnętrznego elementu ustawialnego. jeśli potrzebujesz tylko skupić element własny - nie wysyłaj żadnych parametrów selektora do dyrektywy:
}
przykład użycia dla prostego elementu:
przykład użycia dla elementu wewnętrznego (zwykle dla dynamicznego wstrzykiwanego elementu, takiego jak dyrektywa z szablonem):
możesz użyć dowolnego selektora jQuery zamiast „input”
źródło
Edytuję dyrektywę focusMe Marka Rajcoka, aby pracować dla wielu fokusów w jednym elemencie.
HTML:
w sterowniku AngularJs:
Dyrektywa AngulaJS:
źródło
Chcę przyczynić się do tej dyskusji po znalezieniu lepszego rozwiązania i nie znalezieniu go, zamiast tego muszę go utworzyć.
Kryteria: 1. Rozwiązanie powinno być niezależne od zakresu kontrolera nadrzędnego, aby zwiększyć możliwość ponownego użycia. 2. Unikaj używania $ watch do monitorowania niektórych warunków, jest to zarówno powolne, zwiększa rozmiar pętli podsumowania i utrudnia testowanie. 3. Unikaj $ limitu czasu lub $ zasięgu. $ Apply (), aby uruchomić pętlę podsumowania. 4. Element wejściowy jest obecny w elemencie, w którym dyrektywa jest stosowana jako otwarta.
To rozwiązanie najbardziej mi się podobało:
Dyrektywa:
HTML:
Mam nadzieję, że to pomoże komuś tam!
źródło
To proste ... spróbuj tego
HTML
javascript
źródło
Jeśli chcesz ustawić fokus na konkretnym elemencie, możesz zastosować poniższe podejście.
Utwórz usługę o nazwie
focus
.Wstaw go do kontrolera, z którego chcesz zadzwonić.
Zadzwoń do tej usługi.
źródło
Myślę, że dyrektywa jest niepotrzebna. Użyj identyfikatora HTML i atrybutów klasy, aby wybrać wymagany element, a usługa skorzystaj z document.getElementById lub document.querySelector, aby zastosować fokus (lub odpowiedniki jQuery).
Znaczniki to standardowe dyrektywy HTML / kątowe z dodanym identyfikatorem / klasami do wyboru
Kontroler transmituje zdarzenie
W interfejsie usługa korzysta z querySelector - jeśli istnieje wiele dopasowań (powiedzmy ze względu na klasę), zwróci tylko pierwszy
Możesz użyć $ timeout (), aby wymusić cykl podsumowania
źródło
Po prostu wrzucam kawę.
źródło