입력 필드에 초점을 설정하는 방법은 무엇입니까?


759

AngularJS의 입력 필드에 초점을 맞추는 '각도'는 무엇입니까?

보다 구체적인 요구 사항 :

  1. 모달은 미리 정의에 설정 초점 열립니다<input> 이 모달 내부.
  2. <input>(예를 들어 일부 버튼을 클릭하여) 보일 때 마다 초점을 설정하십시오.

나는 첫 번째 요구 사항 달성하기 위해 노력 과를autofocus , 그러나 이것은 모달 처음 열리고 특정 브라우저 (파이어 폭스에서 작동하지 않는 등) 경우에만 작동합니다.

도움을 주시면 감사하겠습니다.

답변:


579
  1. 모달이 열리면이 모달 내부의 사전 정의 된 <입력>에 초점을 설정하십시오.

지시어를 정의하고 속성 / 트리거를 $ watch하여 요소를 언제 포커스해야하는지 알 수있게하십시오.

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

플 런커

모달 시간을 렌더링하는 데 $ timeout이 필요한 것 같습니다.

'2.' <입력>이 보일 때마다 (예 : 버튼을 클릭하여) 초점을 설정하십시오.

본질적으로 위와 같은 지시문을 작성하십시오. 범위 속성을 확인하고 true가되면 (ng-click 핸들러에서 설정) 실행하십시오 element[0].focus(). 사용 사례에 따라 $ timeout이 필요하거나 필요하지 않을 수 있습니다.

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

플 런커


2013 년 7 월 업데이트 : 소수의 사람들이 원래의 분리 범위 지시문을 사용하고 포함 된 입력 필드 (예 : 모달의 입력 필드)에 문제가 있음을 보았습니다. 새로운 범위가 없거나 (또는 ​​새로운 자식 범위가없는) 지시문은 약간의 고통을 완화해야합니다. 따라서 위의 격리 범위를 사용하지 않도록 답변을 업데이트했습니다. 아래는 원래 답변입니다.

분리 범위를 사용하는 1에 대한 원래 답변 :

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

플 런커 .

분리 범위를 사용하여 2에 대한 원래 답변 :

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

플 런커 .

지시문에서 trigger / focusInput 속성을 재설정해야하므로 양방향 데이터 바인딩에는 '='가 사용됩니다. 첫 번째 지시문에서 '@'이면 충분했습니다. 또한 @을 사용하면 @가 항상 문자열이되므로 트리거 값을 "true"와 비교합니다.


1
@Josh의 "초점"지시문도 참조하십시오. stackoverflow.com/a/14859639/215945 그는 구현에 격리 범위를 사용하지 않았습니다.
Mark Rajcok

2
@MarkRajcok는 이것에 대해 궁금합니다.이 버전은 작동하지만 ng-model입력 필드에 on을 설정 하면 격리 범위가 사용되는이 지시문을 사용할 때 모델 값이 손실됩니다. 분리 범위를 사용하지 않고 Josh 버전을 사용하면 문제가 발생하지 않습니다. 여전히 초보자이며 차이점을 이해하고 싶습니다. 그것을 보여주는 Plunker 가 있습니다.
Sunil D.

1
# 1은 AngularJS 1.0.6에서 잘 작동한다는 것을 알았습니다. 그러나 디버거에서 실행할 때 모달을 닫았다가 다시 열 때마다 이전보다 초점을 설정하는 함수에 대한 추가 호출이 하나 더 있음을 알았습니다. 때 시계를 바인딩 해제하기 위해 해당 기능을 약간 수정 value != "true"했으며 문제가 해결되었습니다.
앤드류 브라운

1
그래서 ... 상태 저장 페이지에서 $ watch는 $ watch이고 각도 개발자는 $ watch를 좋아하기 때문에 같은 일이 일어났습니다 ... 음 나는 문제에 부딪 혔습니다. 아래 제안.
벤 레시

3
흠 나를 위해 코드가 제대로 작동하는 것을 볼 수 있고 element [0]이 올바른 제어입니다. 그러나 .focus ()는 포커스를 트리거하지 않습니다. 아마도 부트 스트랩이나 다른 것이 이것을 방해하고 있습니까?
소닉 소울

264

(편집 :이 설명 아래에 업데이트 된 솔루션을 추가했습니다)

마크 Rajcok 그 사람 ... 그리고 그의 대답은 올바른 대답이지만, 결함 (죄송 마크)했다 ...

... 부울을 사용하여 입력에 초점을 맞춘 다음 입력을 흐리게 한 다음 다시 입력에 초점을 맞추십시오. 부울을 false로 재설정 한 다음 $ digest를 재설정 한 다음 다시 true로 재설정하지 않으면 작동하지 않습니다. 식에 문자열 비교를 사용하더라도 문자열을 $ digest로 변경 한 다음 다시 변경해야합니다. (이는 blur 이벤트 핸들러로 해결되었습니다.)

따라서이 대체 솔루션을 제안합니다.

잊혀진 Angular의 기능인 이벤트를 사용하십시오.

JavaScript는 결국 이벤트를 좋아합니다. 이벤트는 본질적으로 느슨하게 결합되어 있으며 더 좋은 것은 $ digest에 $ watch를 추가하는 것을 피합니다.

app.directive('focusOn', function() {
   return function(scope, elem, attr) {
      scope.$on(attr.focusOn, function(e) {
          elem[0].focus();
      });
   };
});

이제 다음과 같이 사용할 수 있습니다.

<input type="text" focus-on="newItemAdded" />

그런 다음 앱의 어느 곳에서나

$scope.addNewItem = function () {
    /* stuff here to add a new item... */

    $scope.$broadcast('newItemAdded');
};

이런 식으로 모든 종류의 일을 할 수 있기 때문에 이것은 굉장합니다. 하나, 당신은 이미 존재하는 이벤트에 묶을 수 있습니다. 또 다른 일로는 앱의 다른 부분이 구독 할 수있는 앱 게시 이벤트의 다른 부분을 가져서 스마트 한 일을 시작합니다.

어쨌든, 이런 종류의 일이 나에게 "사건 주도"를 외칩니다. Angular 개발자로서 $ scope 모양의 페그를 이벤트 모양 구멍에 망치려고 열심히 노력한다고 생각합니다.

최고의 솔루션입니까? 난 몰라 그것은이다 솔루션입니다.


업데이트 된 솔루션

아래의 @ ShimonRachlenko의 의견 후에이 작업을 약간 변경했습니다. 이제 "장면에서"이벤트를 처리하는 지시문과 서비스를 조합하여 사용합니다.

그 외에는 위에서 설명한 것과 동일한 원칙입니다.

여기에 빠른 데모 Plunk가 있습니다

용법

<input type="text" focus-on="focusMe"/>
app.controller('MyCtrl', function($scope, focus) {
    focus('focusMe');
});

출처

app.directive('focusOn', function() {
   return function(scope, elem, attr) {
      scope.$on('focusOn', function(e, name) {
        if(name === attr.focusOn) {
          elem[0].focus();
        }
      });
   };
});

app.factory('focus', function ($rootScope, $timeout) {
  return function(name) {
    $timeout(function (){
      $rootScope.$broadcast('focusOn', name);
    });
  }
});

3
당신은에 전화를 포장 할 필요 $broadcast$timeout컨트롤러를 입력에 대한 작업이 원하는 경우. 그렇지 않으면 좋은 해결책입니다.
Shimon Rachlenko

@ ShimonRachlenko-감사합니다. 그러나 $ timeout의 의미를 잘 모르겠습니다. 컨트롤러 생성자가 처리 될 때 브로드 캐스트하고 싶다면 바로 브로드 캐스트하십시오. 타임 아웃은 아무것도하지 않고 이벤트 루프에서 나중에 실행하도록 브로드 캐스트를 연기합니다.
Ben Lesh

1
예, 지시문을 초기화하기에 충분합니다. 또한 지시문이 듣기 시작하기 전에 이벤트가 브로드 캐스트됩니다. 다시, 이것은 페이지에 들어갈 때 지시문을 트리거하려는 경우에만 필요합니다.
Shimon Rachlenko

2
당신은 맞습니다. 로드에 초점을 맞추는 데 사용하지 않은 것 같습니다. 더 강력한 것으로 답변을 업데이트하겠습니다.
Ben Lesh

1
이것은 지금까지 가장 우아한 "각도"솔루션입니다. 이 문제가 처음 발생했을 때 대부분 코드를 복사했지만 모듈을 만들게되어 기쁩니다. 나는 솔직히 그것을 핵심 각도로 가져 오는 것이 가치가 있다고 생각합니다.
Randolpho

241

나는 당신이 정말로 필요한 모든 것이 이것 일 때 다른 대답 중 일부가 지나치게 복잡하다는 것을 발견했습니다

app.directive('autoFocus', function($timeout) {
    return {
        restrict: 'AC',
        link: function(_scope, _element) {
            $timeout(function(){
                _element[0].focus();
            }, 0);
        }
    };
});

사용법은

<input name="theInput" auto-focus>

우리는 타임 아웃을 사용하여 DOM의 것들이 0이더라도 렌더링 할 수있게합니다. 적어도 그것을 기다립니다.


1
이 작업을 수행하는 몇 가지 방법이 있습니다. 실제로 간단하고 쉬운 방법 중 하나는 스코프 (제어기)에서 버튼을 클릭 할 때 집중하려는 항목의 ID를 설정하는 것입니다. 지시는 단순히 이것을 들어라. 이 경우 특정 위치, 특히 해당 페이지 내 어딘가에 지시문을 배치 할 필요가 없습니다 (이러한 종류의 감시자 지시문은 과거에 성공했으며 특히 초점을 맞추고 스크롤하는 데 사용했습니다)-그렇다면 jquery를 사용하면 (이를 더 간단하게 만들 수 있습니다) 그냥 요소 ID를 찾아 초점을 맞추십시오
ecancil

14
입력이 팝업 모달에있는 경우 시간 초과가 0 인 솔루션이 작동하지 않습니다. 그러나 10ms조차도 문제를 해결합니다
Eugene Fidelin

@ ecancil : 가장 간단하기 때문에 접근 방식이 마음에 들지만 모달 모양의 애니메이션으로 인해 커서가 입력 외부에서 깜박이기 때문에 IE에서 시간 초과를 ~ 500ms로 설정해야합니다. 애니메이션이 끝날 때 이런 일이 일어날 수있는 좋은 방법을 모르겠으므로 500ms로 무차별 강제 실행하십시오.
Dev93

데이터베이스에서 더 많은 데이터를 가져와야 할 경우 컨트롤러가 풀링 데이터를 완료 할 때까지 기다려야하므로 0 대신 충분한 시간을 추가하십시오.
Ali Adravi

1
@Ade와 같은 사람들을 위해 이것을 간단하게 사용하고 싶다면 ng-click: 버튼을 클릭하면 ng-click="showInput = !showInput입력 내용 이 있다고 가정 해 봅시다 . 그런 다음 실제 입력에을 추가하십시오 ng-if="showInput". 버튼을 전환하면 매번 지시문이 다시 실행됩니다. 내가 사용 ng-show하는 동안 잘못된 접근 방식으로 문제가 발생했습니다.
JVG

91

HTML에는 속성이 autofocus있습니다.

<input type="text" name="fname" autofocus>

http://www.w3schools.com/tags/att_input_autofocus.asp


29
불행히도, 이것은 한 번만 작동합니다. 나는 Angular edit in place 상황에서 이것을 사용했으며 Firefox에서는 처음이 아니라 Chrome에서 처음으로 훌륭하게 작동했습니다. Chrome에서 다른 항목을 클릭하여 제자리에서 수정하거나 같은 항목을 다시 클릭해도 더 이상 초점이 맞지 않습니다. 문서 상태는 페이지로드에서 작동하며 Angular 앱에서는 한 번만 발생합니다. 이 단순한 것만으로도 우리 모두는 20 %를 벌고있는 해변에 앉아있을 것입니다!
Nocturno

62

각도에 내장 된 jqlite 기능을 사용할 수도 있습니다.

angular.element('.selector').trigger('focus');


2
jquery가로드되지 않은 경우 : angular.forEach (document.querySelectorAll ( '. selector'), function (elem) {elem.focus ();});
Dan Benamy

29
그것을 컨트롤러에 넣는 것은 나쁜 습관이 아닙니까?
VitalyB

2
이 jqlite 라인을 컨트롤러에 넣는 것이 좋지 않은 경우,이 jqlite 라인을 지시문에 넣는 것이 낫지 않습니까?
스포츠

3
나는 이것을 얻는다 :Looking up elements via selectors is not supported by jqLite!
Maria Ines Parnisari

1
@VitalyB 아약스 호출 후 요소를 흐리게 처리 해야하는 경우가있었습니다. 컨트롤러 내부의 콜백에 한 줄의 순수 JS를 추가하거나 해당 입력의 흐림을 위해 독점적으로 전체 지시문을 작성할 수 있습니다. 방금 번거 로움을 느꼈기 때문에 첫 번째 옵션을 선택했습니다.
Sebastianb

55

이것은 입력 제어에 초점을 맞추는 각도 방식으로 잘 작동합니다.

angular.element('#elementId').focus()

이것은 작업을 수행하는 순수한 각도 방법은 아니지만 구문은 각도 스타일을 따릅니다. Jquery는 Angular (jQLite => JQuery Light)를 사용하여 간접적으로 직접 DOM에 액세스합니다.

필요한 경우이 코드를 요소에 직접 액세스 할 수있는 간단한 각도 지시문에 쉽게 넣을 수 있습니다.


이것이 ViewModel-apps에 대한 훌륭한 접근 방법인지 확실하지 않습니다. Angular에서는 지시문을 통해 수행해야합니다.
Agat

예 : 누군가 texbox A를 변경하고 팝업을 표시하고 다른 텍스트 상자 B에 포커스를 설정해야하는 경우
Sanjeev Singh

1
이것을 사용할 때이 오류가 발생합니다 :Looking up elements via selectors is not supported by jqLite!
JVG

6
내가 알 수있는 한 jQuery를 먼저 의존성으로로드해야하며,이 경우 angular.element에는 래퍼가됩니다 $() / jQuery(). 그렇지 않으면 이것이 작동하지 않으며 기본적으로 jQuery를 사용하고 있습니다 (그러나 내가 틀렸다면 수정하십시오)
JVG

@Jascination : jqLite는 jQuery 의존성을 제거하기 위해 개발되었습니다. DOM의 요소에 액세스하기 위해 전체 jQuery가 필요하지 않습니다. 그러나 jQuery가 설치되어 있으면 Angular는 jQuery를 참조합니다. 이것을 확인하십시오 : docs.angularjs.org/api/angular.element
Sanjeev Singh

31

나는 $ timeout이 요소를 창조에 집중시키는 좋은 방법이라고 생각하지 않습니다. 다음은 내장 된 각도 기능을 사용하여 각도 문서의 어두운 깊이에서 파낸 방법입니다. 사전 링크 및 사후 링크 기능을 위해 "link"속성을 "pre"및 "post"로 분리 할 수있는 방법에 주목하십시오.

작업 예 : http://plnkr.co/edit/Fj59GB

// this is the directive you add to any element you want to highlight after creation
Guest.directive('autoFocus', function() {
    return {
        link: {
            pre: function preLink(scope, element, attr) {
                console.debug('prelink called');
                // this fails since the element hasn't rendered
                //element[0].focus();
            },
            post: function postLink(scope, element, attr) {
                console.debug('postlink called');
                // this succeeds since the element has been rendered
                element[0].focus();
            }
        }
    }
});
<input value="hello" />
<!-- this input automatically gets focus on creation -->
<input value="world" auto-focus />

전체 AngularJS 지시문 : https://docs.angularjs.org/api/ng/service/$compile


2
[0] .focus () 요소를 $ timeout에 래핑하여 작동하도록했습니다.
codin

@bbodenmiller 내 모달에는 페이드 아웃 기능이 적용되어 요소가 생성되면 보이지 않습니다 (100 % 투명). 브라우저는 포커스 호출을 자동으로 차단합니다. 분명히 몇 밀리 초가지나면서 거의 투명하지만 가시적 인 입력 / 버튼에 초점을 맞출 수 있습니다.
snowindy

1
문서에 따라 "링크"기능은 기본적으로 "postLink"입니다. 또한보십시오 : bennadel.com/blog/…
jody tate

17

내 원래 해결책은 다음과 같습니다.

플 런커

var app = angular.module('plunker', []);
app.directive('autoFocus', function($timeout) {
    return {
        link: function (scope, element, attrs) {
            attrs.$observe("autoFocus", function(newValue){
                if (newValue === "true")
                    $timeout(function(){element[0].focus()});
            });
        }
    };
});

그리고 HTML :

<button ng-click="isVisible = !isVisible">Toggle input</button>
<input ng-show="isVisible" auto-focus="{{ isVisible }}" value="auto-focus on" />

그것이하는 일 :

ng-show로 표시 될 때 입력의 초점을 맞 춥니 다. 여기서 $ watch 또는 $ on을 사용하지 않습니다.


실제로 {{isVisible}}에서 시계를 만들고 있다고해서 "$ watch 사용 안함"문이 잘못되었다고 생각합니다.
masimplo

예, 당신이 옳다고 생각합니다. 그러나 여전히 쉬운 방법으로 사용됩니다.
Edhowler

17

최근 모델과 마찬가지로 양방향 바인딩 포커스 지시문을 작성했습니다.

다음과 같이 포커스 지시문을 사용할 수 있습니다.

<input focus="someFocusVariable">

true컨트롤러의 임의의 위치에서 someFocusVariable 범위 변수를 만들면 입력이 집중됩니다. 입력을 "흐리게"하려면 someFocusVariable을 false로 설정할 수 있습니다. Mark Rajcok의 첫 번째 대답과 같지만 양방향 바인딩이 있습니다.

지시어는 다음과 같습니다.

function Ctrl($scope) {
  $scope.model = "ahaha"
  $scope.someFocusVariable = true; // If you want to focus initially, set this to true. Else you don't need to define this at all.
}

angular.module('experiement', [])
  .directive('focus', function($timeout, $parse) {
    return {
      restrict: 'A',
      link: function(scope, element, attrs) {
          scope.$watch(attrs.focus, function(newValue, oldValue) {
              if (newValue) { element[0].focus(); }
          });
          element.bind("blur", function(e) {
              $timeout(function() {
                  scope.$apply(attrs.focus + "=false"); 
              }, 0);
          });
          element.bind("focus", function(e) {
              $timeout(function() {
                  scope.$apply(attrs.focus + "=true");
              }, 0);
          })
      }
    }
  });

용법:

<div ng-app="experiement">
  <div ng-controller="Ctrl">
    An Input: <input ng-model="model" focus="someFocusVariable">
    <hr>
        <div ng-click="someFocusVariable=true">Focus!</div>  
        <pre>someFocusVariable: {{ someFocusVariable }}</pre>
        <pre>content: {{ model }}</pre>
  </div>
</div>

바이올린은 다음과 같습니다.

http://fiddle.jshell.net/ubenzer/9FSL4/8/


이것이 정답이어야합니다. 모든 사용 사례를 다룹니다.
Kunal

11

Bootstrap 플러그인과 함께 Angular를 사용하는 사람들을 위해 :

http://angular-ui.github.io/bootstrap/#/modal

opened모달 인스턴스 의 약속에 연결할 수 있습니다 .

modalInstance.opened.then(function() {
        $timeout(function() {
            angular.element('#title_input').trigger('focus');
        });
    });

modalInstance.result.then(function ( etc...

좋은! 그러나 내 경우에는 $timeoutwith 50ms대신 필요합니다 0.
lk_vc

8

나는 일반적인 표현을 사용하는 것이 유용하다는 것을 알았습니다. 이 방법으로 입력 텍스트가 유효 할 때 자동으로 초점 이동과 같은 작업을 수행 할 수 있습니다

<button type="button" moo-focus-expression="form.phone.$valid">

또는 사용자가 고정 길이 필드를 완료하면 자동으로 초점을 맞 춥니 다

<button type="submit" moo-focus-expression="smsconfirm.length == 6">

물론로드 후 초점

<input type="text" moo-focus-expression="true">

지시문의 코드 :

.directive('mooFocusExpression', function ($timeout) {
    return {
        restrict: 'A',
        link: {
            post: function postLink(scope, element, attrs) {
                scope.$watch(attrs.mooFocusExpression, function (value) {

                    if (attrs.mooFocusExpression) {
                        if (scope.$eval(attrs.mooFocusExpression)) {
                            $timeout(function () {
                                element[0].focus();
                            }, 100); //need some delay to work with ng-disabled
                        }
                    }
                });
            }
        }
    };
});

7

좀비를 부활시키지 말고 내 지시를 꽂지 마십시오 (확실히 내가하고있는 일입니다).

https://github.com/hiebj/ng-focus-if

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

<input focus-if />

(function() {
    'use strict';
    angular
        .module('focus-if', [])
        .directive('focusIf', focusIf);

    function focusIf($timeout) {
        function link($scope, $element, $attrs) {
            var dom = $element[0];
            if ($attrs.focusIf) {
                $scope.$watch($attrs.focusIf, focus);
            } else {
                focus(true);
            }
            function focus(condition) {
                if (condition) {
                    $timeout(function() {
                        dom.focus();
                    }, $scope.$eval($attrs.focusDelay) || 0);
                }
            }
        }
        return {
            restrict: 'A',
            link: link
        };
    }
})();

나는이 지시어를 사용하고 있으며 훌륭하게 작동하고 일반적인 문제를 해결하며 지나치게 복잡하지 않습니다. $ timeout-free 솔루션을 찾으십시오. Angular 1.1 및 1.2의 경우 초점이 "로드맵"이라는 의견을 계속 찾으십시오. 그러나 2.x를 사용하고 있으며 여전히 초점 관리는 없습니다. 허.
tekHedd

6

우선, 공식적인 초점을 맞추는 방법 은 1.1로드맵입니다 . 한편, 설정 포커스를 구현하기위한 지시문을 작성할 수 있습니다.

둘째, 항목을 표시 한 후 항목에 초점을 설정하려면 현재 해결 방법이 필요합니다. 요소 focus ()에 대한 호출을$timeout .

포커스, 블러 및 선택에 대해 동일한 컨트롤러-수정 -DOM 문제가 있기 때문에 ng-target지시어를 제안 합니다.

<input type="text" x-ng-model="form.color" x-ng-target="form.colorTarget">
<button class="btn" x-ng-click="form.colorTarget.focus()">do focus</button>

앵귤러 스레드 : http://goo.gl/ipsx4 및 자세한 내용은 여기 ( http://goo.gl/4rdZa)에 블로그를 게시하십시오.

다음 지시문은 속성에 .focus()지정된대로 컨트롤러 내에 함수 를 만듭니다 ng-target. (그것은 생성 .blur()과를 .select()너무.) 데모 : http://jsfiddle.net/bseib/WUcQX/


로드맵 참조의 경우 +1 사실 1.2의 문서에서 여전히 불안정하다고 간주되는 것을 보았습니다 ( docs.angularjs.org/api/ng.directive:ngFocus )
Edwin Dalorzo

27
@EdwinDalorzo는 ngFocus처리 할 수있는 방법이 나타납니다 focus이벤트를하지 수있는 방법 설정 요소에 초점을.
teleclimber

6

직접 지시문을 작성하는 대신 단순히 자바 스크립트 함수를 사용하여 초점을 맞출 수 있습니다.

다음은 예입니다.

html 파일에서 :

<input type="text" id="myInputId" />

예를 들어, 포커스를 활성화하려는 컨트롤러의 파일 자바 스크립트에서 :

document.getElementById("myInputId").focus();

9
이것은 '각도'가 아니며 컨트롤러에서 DOM을 터치하도록 사람들에게 조언하지 않습니다.
smajl September

Angular는 바닐라를 추적하거나 다른 모든 항목과 동기화 할 수 없기 때문에 Angular에서 사용하지 않는 것이 가장 좋습니다.
에드가 퀸 테로

4

ng-click으로 제어되는 간단한 초점을 원한다면.

HTML :

<input ut-focus="focusTigger">

<button ng-click="focusTrigger=!focusTrigger" ng-init="focusTrigger=false"></button>

지령:

'use strict'

angular.module('focus',['ng'])
.directive('utFocus',function($timeout){
    return {
        link:function(scope,elem,attr){
            var focusTarget = attr['utFocus'];
            scope.$watch(focusTarget,function(value){
                $timeout(function(){
                    elem[0].focus();
                });
            });
        }
    }
});

4

모달과 잘 작동하는 간단한 것 :

.directive('focusMeNow', ['$timeout', function ($timeout)
{
    return {
        restrict: 'A',

        link: function (scope, element, attrs)
        {


            $timeout(function ()
            {
                element[0].focus();
            });



        }
    };
}])

<input ng-model="your.value" focus-me-now />

나 한테 딱이야. 감사합니다
Alexander

3

postLinking에서 데코레이션 된 요소에 초점을 맞추는 지시문을 만들 수 있습니다.

angular.module('directives')
.directive('autoFocus', function() {
    return {
        restrict: 'AC',
        link: function(_scope, _element) {
            _element[0].focus();
        }
    };
});

그런 다음 HTML에서 :

<input type="text" name="first" auto-focus/> <!-- this will get the focus -->
<input type="text" name="second"/>

postLinking은 HTML 처리에서만 발생하기 때문에 ng-show가 아닌 ​​모달 및 ng-if 토글 요소에서 작동합니다.


3

Mark와 Blesh는 큰 대답을했습니다. 그러나 Mark 's에는 Blesh가 지적한 결함이 있습니다 (구현하기가 복잡함). Blesh의 답변에는 실제로 필요한 모든 것이 방법 일 때 프론트 엔드에 포커스 요청을 보내는 것에 관한 서비스를 만드는 데 의미 론적 오류가 있다고 생각합니다 모든 지시문이 청취 될 때까지 이벤트를 지연 시키십시오.

그래서 여기 내가 Blesh의 답변에서 많은 것을 훔치지 만 컨트롤러 이벤트의 의미와 "로드 후"서비스를 별도로 유지하는 결과가 있습니다.

이를 통해 컨트롤러 요소를 특정 요소에 초점을 맞추는 것 이외의 용도로 쉽게 연결할 수 있으며 필요한 경우에만 "애프터로드"기능의 오버 헤드가 발생할 수 있습니다.

용법

<input type="text" focus-on="controllerEvent"/>
app.controller('MyCtrl', function($scope, afterLoad) {
  function notifyControllerEvent() {
      $scope.$broadcast('controllerEvent');
  }

  afterLoad(notifyControllerEvent);
});

출처

app.directive('focusOn', function() {
   return function(scope, elem, attr) {
      scope.$on(attr.focusOn, function(e, name) {
        elem[0].focus();
      });
   };
});

app.factory('afterLoad', function ($rootScope, $timeout) {
  return function(func) {
    $timeout(func);
  }
});

유일한 대답은 내가 (완전한 초보자) 이해할 수 있습니다. "afterLoad (notifyControllerEvent);"대신 "notifyControllerEvent ()"를 사용했습니다. 그렇지 않으면 오류가 발생했습니다.
Vel Murugan S

3

이것도 사용할 수 있습니다 ngModelController. 1.6 이상으로 작업하기 (이전 버전에서는 모름)

HTML

<form name="myForm">
    <input type="text" name="myText" ng-model="myText">
</form>

JS

$scope.myForm.myText.$$element.focus();

-

NB : 상황에 따라 타임 아웃 기능을 사용해야 할 수도 있습니다.

NB² :를 사용할 때 controllerAs와 거의 같습니다. 그냥 교체 name="myForm"name="vm.myForm", 그리고 JS에서 vm.myForm.myText.$$element.focus();.


3

아마도 ES6 시대에 가장 간단한 솔루션 일 것입니다.

하나의 라이너 지시문을 추가하면 Angular.js에서 HTML 'autofocus'속성이 효과적입니다.

.directive('autofocus', ($timeout) => ({link: (_, e) => $timeout(() => e[0].focus())}))

이제 다음과 같은 HTML5 자동 초점 구문을 사용할 수 있습니다.

<input type="text" autofocus>

@Stephane 그렇습니다..directive('autofocus', ['$timeout', ($timeout) => ({link: (_, e) => $timeout(() => e[0].focus())})])
Michael Plautz

2

여기 초보자 일뿐이지만 이 지시문 을 사용하여 ui.bootstrap.modal 에서 작동하게 할 수 없었 습니다.

directives.directive('focus', function($timeout) {
    return {
        link : function(scope, element) {
            scope.$watch('idToFocus', function(value) {
                if (value === element[0].id) {
                    $timeout(function() {
                        element[0].focus();
                    });
                }
            });
        }
    };
});

그리고 $ modal.open 메소드에서 folowing을 사용하여 초점을 두어야 할 요소를 나타냅니다.

var d = $modal.open({
        controller : function($scope, $modalInstance) {
            ...
            $scope.idToFocus = "cancelaAteste";
    }
        ...
    });

템플릿에서 나는 이것을 가지고있다 :

<input id="myInputId" focus />

2

다음 지시문이 나를 위해 속였습니다. 입력에 동일한 자동 초점 html 속성을 사용하십시오.

.directive('autofocus', [function () {
    return {
        require : 'ngModel',
        restrict: 'A',
        link: function (scope, element, attrs) {
            element.focus();
        }
    };
}])

1
jQuery가 포함되어 있지 않으면이를 실행하는 동안 오류가 발생합니다. 대신 element [0] .focus ()
Ryan M

2

modalInstance를 사용 중이고 오브젝트가있는 경우 "then"을 사용하여 모달을 연 후 조치를 수행 할 수 있습니다. modalInstance를 사용하지 않고 모달을 열도록 하드 코딩 된 경우 이벤트를 사용할 수 있습니다. $ timeout은 좋은 해결책이 아닙니다.

당신은 할 수 있습니다 (Bootstrap3) :

$("#" + modalId).on("shown.bs.modal", function() {
    angular.element("[name='name']").focus();
});

modalInstance에서 라이브러리를 열어 모달을 연 후 코드를 실행하는 방법을 확인할 수 있습니다.

이와 같이 $ timeout을 사용하지 마십시오. $ timeout은 0, 1, 10, 30, 50, 200 이상일 수 있습니다. 이것은 클라이언트 컴퓨터 및 모달을 여는 프로세스에 따라 다릅니다.

$ timeout을 사용하지 마십시오. 초점을 맞출 수있는 방법을 알려줍니다.)

나는 이것이 도움이되기를 바랍니다! :)


2

원하는 포커스 요소를 지시문 템플릿에 삽입하면 이전 답변이 모두 작동하지 않습니다. 다음 지시문은 단순 요소 또는 지시문 삽입 요소 모두에 적합합니다 ( typescript로 작성했습니다 ). 내부 포커스 가능 요소에 대한 선택기를 허용합니다. self 요소에 초점을 맞추고 싶다면 지시자에게 selector 매개 변수를 보내지 마십시오.

module APP.Directives {

export class FocusOnLoadDirective implements ng.IDirective {
    priority = 0;
    restrict = 'A';

    constructor(private $interval:any, private $timeout:any) {

    }

    link = (scope:ng.IScope, element:JQuery, attrs:any) => {
        var _self = this;
        var intervalId:number = 0;


        var clearInterval = function () {
            if (intervalId != 0) {
                _self.$interval.cancel(intervalId);
                intervalId = 0;
            }
        };

        _self.$timeout(function(){

                intervalId = _self.$interval(function () {
                    let focusableElement = null;
                    if (attrs.focusOnLoad != '') {
                        focusableElement = element.find(attrs.focusOnLoad);
                    }
                    else {
                        focusableElement = element;
                    }
                    console.debug('focusOnLoad directive: trying to focus');
                    focusableElement.focus();
                    if (document.activeElement === focusableElement[0]) {
                        clearInterval();
                    }
                }, 100);

                scope.$on('$destroy', function () {
                    // Make sure that the interval is destroyed too
                    clearInterval();
                });

        });
    };

    public static factory = ():ng.IDirectiveFactory => {
        let directive = ($interval:any, $timeout:any) => new FocusOnLoadDirective($interval, $timeout);
        directive.$inject = ['$interval', '$timeout'];
        return directive;
    };
}

angular.module('common').directive('focusOnLoad', FocusOnLoadDirective.factory());

}

간단한 요소의 사용 예 :

<button tabindex="0" focus-on-load />

내부 요소의 사용 예 (일반적으로 템플릿이있는 지시문과 같은 동적 주입 요소의 경우) :

<my-directive focus-on-load="input" />

"입력"대신 모든 jQuery 선택기를 사용할 수 있습니다


2

Mark Rajcok의 focusMe 지시문을 편집하여 한 요소에서 여러 초점에 작동합니다.

HTML :

<input  focus-me="myInputFocus"  type="text">

AngularJs 컨트롤러에서 :

$scope.myInputFocus= true;

AngulaJS 지시어 :

app.directive('focusMe', function ($timeout, $parse) {
    return {
        link: function (scope, element, attrs) {
            var model = $parse(attrs.focusMe);
            scope.$watch(model, function (value) {
                if (value === true) {
                    $timeout(function () {
                        scope.$apply(model.assign(scope, false));
                        element[0].focus();
                    }, 30);
                }
            });
        }
    };
});

1

더 나은 솔루션을 찾고 그것을 찾지 않고 대신 만들어야 할 때이 토론에 기여하고 싶습니다.

기준 : 1. 솔루션은 재사용 성을 높이기 위해 상위 컨트롤러 범위와 독립적이어야합니다. 2. $ watch를 사용하여 일부 상태를 모니터링하지 마십시오. 속도가 느리고 다이제스트 루프의 크기가 커지고 테스트가 더 어렵습니다. 3. $ timeout 또는 $ scope. $ apply ()를 피하여 다이제스트 루프를 트리거하십시오. 4. 지시어가 열린 상태에서 요소 내에 입력 요소가 존재한다.

이것이 내가 가장 좋아하는 솔루션입니다.

지령:

.directive('focusInput', [ function () {
    return {
        scope: {},
        restrict: 'A',
        compile: function(elem, attr) {
            elem.bind('click', function() {
                elem.find('input').focus();                
            });
        }        
    };
}]);

HTML :

 <div focus-input>
     <input/>
 </div>

나는 이것이 누군가를 도울 수 있기를 바랍니다!


html "label"의 기능을 다시 만들었습니다. "div focus-input"을 "label"로 바꾸고 지시어를 제거하면됩니다.
frst

1

쉬워요 .. 시도해보세요

html

<select id="ddl00">  
 <option>"test 01"</option>  
</select>

자바 스크립트

document.getElementById("ddl00").focus();

문맥에 맞지 않지만 AngularJS 방식은 아닙니다
CodeMonkey

1

특정 요소에 초점을 맞추려면 아래 방법을 사용할 수 있습니다.

  1. 라는 서비스를 만듭니다 focus.

    angular.module('application')
    .factory('focus', function ($timeout, $window) {
        return function (id) {
            $timeout(function () {
                var element = $window.document.getElementById(id);
                if (element)
                    element.focus();
            });
        };
    });
  2. 통화하려는 곳에서 컨트롤러에 삽입하십시오.

  3. 이 서비스에 전화하십시오.


0

지시어가 불필요하다고 생각합니다. HTML id 및 클래스 속성을 사용하여 필수 요소를 선택하고 서비스에서 document.getElementById 또는 document.querySelector를 사용하여 초점 (또는 jQuery에 해당)을 적용하십시오.

마크 업은 선택을 위해 ID / 클래스가 추가 된 표준 HTML / 각도 지시문입니다

<input id="myInput" type="text" ng-model="myInputModel" />

컨트롤러 방송 이벤트

$scope.$emit('ui:focus', '#myInput');

UI 서비스에서 querySelector를 사용합니다-클래스로 인해 일치하는 항목이 여러 개인 경우 첫 번째 항목 만 반환합니다.

$rootScope.$on('ui:focus', function($event, selector){
  var elem = document.querySelector(selector);
  if (elem) {
    elem.focus();
  }
});

다이제스트 사이클을 강제하기 위해 $ timeout ()을 사용할 수 있습니다


0

그냥 커피를 던져.

app.directive 'ngAltFocus', ->
    restrict: 'A'
    scope: ngAltFocus: '='
    link: (scope, el, attrs) ->
        scope.$watch 'ngAltFocus', (nv) -> el[0].focus() if nv
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.