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

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

보다 구체적인 요구 사항 :

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

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

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



답변

  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”와 비교합니다.


답변

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

마크 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);
    });
  }
});


답변

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

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이더라도 렌더링 할 수있게합니다. 적어도 그것을 기다립니다.


답변

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

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

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


답변

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

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


답변

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

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

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

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


답변

나는 $ 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