[angularjs] 각도 방식으로 요소 초점 설정

각도로 포커스 요소를 설정하는 방법에 대한 예제를 찾은 후 대부분이 변수를 사용하여 관찰 한 다음 포커스를 설정하고, 대부분은 포커스를 설정하려는 각 필드에 대해 하나의 다른 변수를 사용하는 것을 확인했습니다. 필드가 많은 양식에서 다양한 변수를 의미합니다.

jquery 방식을 염두에두고 각도 방식으로하고 싶었으므로 요소의 ID를 사용하여 모든 기능에 초점을 맞춘 솔루션을 만들었으므로 각도가 매우 새롭기 때문에 다음과 같은 의견을 듣고 싶습니다. 그 방법이 옳습니다. 문제가 있습니다. 제가 각도에서 더 나은 방법으로이 작업을 수행하는 데 도움이 될 수있는 모든 것이 있습니다.

기본적으로 지시문 또는 기본값의 focusElement로 사용자가 정의한 범위 값을 감시하는 지시문을 만들고 해당 값이 요소의 ID와 같으면 해당 요소가 포커스를 설정합니다.

angular.module('appnamehere')
  .directive('myFocus', function () {
    return {
      restrict: 'A',
      link: function postLink(scope, element, attrs) {
        if (attrs.myFocus == "") {
          attrs.myFocus = "focusElement";
        }
        scope.$watch(attrs.myFocus, function(value) {
          if(value == attrs.id) {
            element[0].focus();
          }
        });
        element.on("blur", function() {
          scope[attrs.myFocus] = "";
          scope.$apply();
        })
      }
    };
  });

어떤 이유로 포커스를 받아야하는 입력은 이런 식으로 수행됩니다.

<input my-focus id="input1" type="text" />

포커스를 설정할 요소는 다음과 같습니다.

<a href="" ng-click="clickButton()" >Set focus</a>

그리고 포커스를 설정하는 예제 함수 :

$scope.clickButton = function() {
    $scope.focusElement = "input1";
}

각도에서 좋은 솔루션입니까? 내 가난한 경험으로 아직 보지 못하는 문제가 있습니까?



답변

솔루션의 문제는 새 범위를 생성하는 다른 지시문 (예 :)에 묶여있을 때 제대로 작동하지 않는다는 것 ng-repeat입니다. 더 나은 솔루션은 컨트롤러 내에서 명령 적으로 요소에 초점을 맞추거나 html에서 선언적으로 요소에 초점을 맞출 수있는 서비스 함수를 만드는 것입니다.

데모

자바 스크립트

서비스

 .factory('focus', function($timeout, $window) {
    return function(id) {
      // timeout makes sure that it is invoked after any other event has been triggered.
      // e.g. click events that need to run before the focus or
      // inputs elements that are in a disabled state but are enabled when those events
      // are triggered.
      $timeout(function() {
        var element = $window.document.getElementById(id);
        if(element)
          element.focus();
      });
    };
  });

지령

  .directive('eventFocus', function(focus) {
    return function(scope, elem, attr) {
      elem.on(attr.eventFocus, function() {
        focus(attr.eventFocusId);
      });

      // Removes bound events in the element itself
      // when the scope is destroyed
      scope.$on('$destroy', function() {
        elem.off(attr.eventFocus);
      });
    };
  });

제어 장치

.controller('Ctrl', function($scope, focus) {
    $scope.doSomething = function() {
      // do something awesome
      focus('email');
    };
  });

HTML

<input type="email" id="email" class="form-control">
<button event-focus="click" event-focus-id="email">Declarative Focus</button>
<button ng-click="doSomething()">Imperative Focus</button>


답변

이 솔루션에 대해 우리는 지시문을 생성하고 주어진 조건이 충족 될 때 포커스를 얻어야하는 DOM 요소에 첨부 할 수 있습니다. 이 접근 방식을 따르면 컨트롤러를 DOM 요소 ID에 연결하지 않습니다.

샘플 코드 지시문 :

gbndirectives.directive('focusOnCondition', ['$timeout',
    function ($timeout) {
        var checkDirectivePrerequisites = function (attrs) {
          if (!attrs.focusOnCondition && attrs.focusOnCondition != "") {
                throw "FocusOnCondition missing attribute to evaluate";
          }
        }

        return {
            restrict: "A",
            link: function (scope, element, attrs, ctrls) {
                checkDirectivePrerequisites(attrs);

                scope.$watch(attrs.focusOnCondition, function (currentValue, lastValue) {
                    if(currentValue == true) {
                        $timeout(function () {
                            element.focus();
                        });
                    }
                });
            }
        };
    }
]);

가능한 사용법

.controller('Ctrl', function($scope) {
   $scope.myCondition = false;
   // you can just add this to a radiobutton click value
   // or just watch for a value to change...
   $scope.doSomething = function(newMyConditionValue) {
       // do something awesome
       $scope.myCondition = newMyConditionValue;
  };

});

HTML

<input focus-on-condition="myCondition">


답변

가능한 한 DOM 조회, 감시 및 전역 이미 터를 피하는 것을 좋아하므로보다 직접적인 접근 방식을 사용합니다. 지시문을 사용하여 지시문 요소에 초점을 맞춘 간단한 기능을 지정하십시오. 그런 다음 컨트롤러 범위 내에서 필요할 때마다 해당 함수를 호출하십시오.

다음은 범위에 연결하는 간단한 방법입니다. 컨트롤러로서의 구문 처리에 대한 전체 스 니펫을 참조하십시오.

지령:

app.directive('inputFocusFunction', function () {
    'use strict';
    return {
        restrict: 'A',
        link: function (scope, element, attr) {
            scope[attr.inputFocusFunction] = function () {
                element[0].focus();
            };
        }
    };
});

그리고 html에서 :

<input input-focus-function="focusOnSaveInput" ng-model="saveName">
<button ng-click="focusOnSaveInput()">Focus</button>

또는 컨트롤러에서 :

$scope.focusOnSaveInput();

이 접근 방식의 이유에 대한 자세한 설명을 제공하고 컨트롤러 사용을 위해 코드 스 니펫을 확장하도록 편집 되었습니다.


답변

당신은 시도 할 수 있습니다

angular.element('#<elementId>').focus();

예를 들어.

angular.element('#txtUserId').focus();

그것은 나를 위해 일하고 있습니다.


답변

또 다른 옵션은 Angular의 내장 pub-sub 아키텍처를 사용하여 지시문에 집중하도록 알리는 것입니다. 다른 접근 방식과 유사하지만 속성에 직접 연결되지 않고 대신 특정 키에 대한 범위를 수신합니다.

지령:

angular.module("app").directive("focusOn", function($timeout) {
  return {
    restrict: "A",
    link: function(scope, element, attrs) {
      scope.$on(attrs.focusOn, function(e) {
        $timeout((function() {
          element[0].focus();
        }), 10);
      });
    }
  };
});

HTML :

<input type="text" name="text_input" ng-model="ctrl.model" focus-on="focusTextInput" />

제어 장치:

//Assume this is within your controller
//And you've hit the point where you want to focus the input:
$scope.$broadcast("focusTextInput");


답변

나는 표현을 선호했습니다. 이렇게하면 필드가 유효하고 특정 길이에 도달 할 때, 물론로드 후에 버튼에 초점을 맞추는 것과 같은 작업을 수행 할 수 있습니다.

<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">

복잡한 형태에서는 초점을 맞추기 위해 추가 범위 변수를 생성 할 필요성도 줄어 듭니다.

참조 https://stackoverflow.com/a/29963695/937997를


답변