2013-03-25 4 views
12

Here is a simplified plunk to illustrate the problemangularjs: ustawienie ostrości na wcześniej ukryty element wejściowy wewnątrz dyrektywy

mam kątową dyrektywę, która kompiluje kodu HTML przed wizualizując go. W html, jest Hiden wejścia, który jest widoczny tylko wtedy, gdy scope.isEditShown jest true:

<input ng-show='isEditShown' type='text' value='{{content.name}}' class='title_edit'/>

wejściowy pojawia się, gdy funkcja scope.titleChange jest wywoływany. Funkcja ta (związany z dyrektywą ng-dblclick) tylko ustawia wierny scope.isEditShown i próbuje wywołać focus() metody jQuery na element wejściowego (poprzednio zapisanego w zakresie, w funkcji łącznika z scope.input = $("input:text", ae);:

scope.isEditShown = true; 
scope.input.focus(); 

w skrócie, Chcę wizualizować wcześniej ukryte dane wejściowe po dwukrotnym kliknięciu i natychmiast skupić się na nim Bezpośrednie skupienie jest potrzebne, ponieważ dane wejściowe są ukryte, gdy straci ostrość (chcę, aby użytkownik mógł natychmiast edytować zawartość wejściową Gdy użytkownik kliknie, wejście jest ukryte)

Problem polega na tym, że wydaje mi się, że nie mogę skupić się na programie elementów wejściowych atycznie. Po eksperymentach odkryłem, że po wykonaniu scope.isEditShown = true; dane wejściowe nie są jeszcze widoczne (= kątowe js nie pokazują go w DOM), a ustawienie ostrości z scope.input.focus(); na ukryte wejście nic nie robi. Kiedy element wejściowy zostaje ostatecznie pokazany, jest nieostry.

Jaki jest kątowy sposób robienia tego, co chcę? Kiedy mogę być pewny, że moje wejście jest pokazane i kiedy mogę skutecznie zadzwonić na numer focus()? UWAGA: jeśli użyję scope.$apply() przed skupieniem się na danych wejściowych, otrzymam wyjątek $apply already in progress. Jeśli zrobię bezpieczną aplikację, foucus nie zostanie podany. Zobacz the plunkr.

(ps: Ja naprawdę chcę zrozumieć, więc nie będę użytku towarzyszących libreries że automagicznie zrobić dla mnie)

+1

Czy można umieścić swój kod w upadać lub jsfiddle? – ganaraj

+2

zrobić bardzo proste demo z tylko tyle kodu, aby reprezentować problem, spróbuj użyć '$ timeout' – charlietfl

+0

@ganaraj: wystarczy edytować odpowiedź z plunkr. – janesconference

Odpowiedz

13

Po wprowadzeniu zmian do niektórych danych zmiennej związanej i trzeba czekać na Odpowiednie renderowanie się stało, musisz użyć słynnego setTimeout 0 (na przemian w usłudze Angular the $timeout).

Oto plunkr, który pokazuje, jak to zrobić.

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

+0

To działa. Pytanie filozoficzne: czy można polegać na limitach czasu? Cała znana mi literatura javascript krzyczy "NIE" w mojej głowie. – janesconference

+0

Javascript jest pojedynczym wątkiem. Nie można również wiedzieć, kiedy kończy się faza renderowania. Jedynym niezawodnym sposobem jest obecnie użycie setTimeout, 0, które zasadniczo mówi javascript, że "rób to jak tylko skończysz ze wszystkim". Również nie ma sposobu przeglądania (zdarzenia) w przeglądarce internetowej po zakończeniu odświeżania przeglądarki. A więc tak, choć wygląda na to, że jest hackerem, a używa się go w wielu miejscach. – ganaraj

+0

Tak, wiem, że działa to jak proces - współdziałanie w wielozadaniowości. Ma to sens: ponieważ kątowy prawdopodobnie nie tworzy swojego stosu wykonawczego, dopóki się nie zakończy, wykonuje całą pracę, zanim wywołanie focus() jest gotowe do wykonania. Dziękuję Ci. – janesconference