it-swarm.com.ru

Как установить фокус на поле ввода?

Что такое "угловой способ", чтобы установить фокус на поле ввода в AngularJS?

Более конкретные требования:

  1. Когда Модальное открыто, установите фокус на предварительно определенный <input> внутри этого Модального.
  2. Каждый раз, когда <input> становится видимым (например, при нажатии какой-либо кнопки), установите фокус на нем.

я пытался выполнить первое требование с помощью autofocus, но это работает только при первом открытии модала и только в определенных браузерах (например, в Firefox не работает).

Любая помощь будет оценена.

741
Misha Moroshko
  1. Когда модальное окно открыто, установите фокус на предварительно определенный <input> внутри этого модального окна.

Определите директиву и задайте ей $ 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.' Каждый раз, когда <input> становится видимым (например, нажатием какой-либо кнопки), установите фокус на него.

Создайте директиву, по сути, похожую на приведенную выше. Следите за некоторым свойством контекста, и когда оно станет истинным (установите его в вашем обработчике ng-click), выполните element[0].focus(). В зависимости от вашего варианта использования вам может понадобиться или не потребоваться тайм-аут в $ для этого:

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

Плункер


Update 7/2013: я видел, как несколько человек использовали мои исходные директивы изолирующего контекста, а затем возникли проблемы со встроенными полями ввода (т. Е. Полем ввода в модале). Директива без новой области (или, возможно, с новой дочерней областью) должна облегчить некоторые проблемы. Так что выше я обновил ответ, чтобы не использовать изолирующие области. Ниже оригинальный ответ:

Оригинальный ответ для 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 в директиве, '=' используется для двустороннего связывания данных. В первой директиве «@» было достаточно. Также обратите внимание, что при использовании «@» мы сравниваем значение триггера с «истиной», поскольку @ всегда приводит к строке.

561
Mark Rajcok

(Правка: я добавил обновленное решение ниже этого объяснения)

Марк Райкок - человек ... и его ответ - правильный ответ, но это имеет был дефект (извините Марк) ...

... Попробуйте использовать логическое значение, чтобы сфокусироваться на входе, затем размыть вход, затем попробуйте использовать его, чтобы снова сфокусировать ввод. Это не сработает, если вы не сбросите логическое значение на false, затем $ digest, а затем не сбросите его на true. Даже если вы используете сравнение строк в своем выражении, вы будете вынуждены изменить строку на что-то другое, $ digest, а затем изменить ее обратно. (Это было решено с помощью обработчика событий размытия.)

Поэтому я предлагаю это альтернативное решение:

Используйте событие, забытое свойство Angular.

В конце концов, JavaScript любит события. События по своей сути слабо связаны, и, что еще лучше, вы избегаете добавления других $ watch к вашему $ digest.

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 в отверстия формы событий.

Это лучшее решение? Я не знаю. Это a решение.


Обновленное решение

После комментария @ 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);
    });
  }
});
258
Ben Lesh

Я нашел некоторые другие ответы слишком сложными, когда все, что вам действительно нужно, это

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

использование 

<input name="theInput" auto-focus>

Мы используем тайм-аут, чтобы позволить объектам в домене визуализироваться, даже если он равен нулю, он, по крайней мере, ждет этого - таким образом, это работает в модальных моделях и еще много чего.

234
ecancil

HTML имеет атрибут autofocus.

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

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

87
Rayron Victor

Вы также можете использовать функциональность jqlite, встроенную в angular.

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

59
JordanC

Это хорошо работает и угловой способ фокусировки ввода управления

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

Это хотя и не чисто угловой способ выполнения задачи, но синтаксис следует угловому стилю. Jquery играет косвенную роль и напрямую обращается к DOM, используя Angular (jQLite => JQuery Light).

При необходимости этот код можно легко поместить в простую угловую директиву, где элемент доступен напрямую.

52
Sanjeev Singh

Я не думаю, что $ timeout - это хороший способ сфокусировать элемент на создании. Вот метод, использующий встроенную угловую функциональность, вырытую из темных глубин угловых документов. Обратите внимание, как атрибут «ссылка» может быть разделен на «pre» и «post» для функций pre-link и post-link.

Рабочий пример: 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

30
Cody Moniz

Вот мое оригинальное решение:

Плункер

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 или $ здесь.

17
Edhowler

Я недавно написал директиву о двухстороннем связывании фокуса, как и модель.

Вы можете использовать директиву focus следующим образом:

<input focus="someFocusVariable">

Если вы сделаете переменную области видимости someFocusVariable где-нибудь в вашем контроллере, true будет сфокусирован. И если вы хотите «размыть» ваш ввод, тогда для someFocusVariable можно установить значение false. Это как первый ответ Марка Райкока, но с двусторонним связыванием.

Вот директива:

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/

17
Umut Benzer

Для тех, кто использует Angular с плагином Bootstrap:

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...
10
BPH

Я нашел полезным использовать общее выражение. Таким образом, вы можете делать такие вещи, как автоматическое перемещение фокуса, когда введенный текст действителен

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

Вместо того, чтобы создавать свою собственную директиву, можно просто использовать функции javascript для достижения цели.

Вот пример.

В HTML-файл:

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

В файле javascript, например, в контроллере, где вы хотите активировать фокус:

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

Не воскрешать зомби и не вставлять мою собственную директиву (хорошо, это именно то, что я делаю):

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

Во-первых, официальный способ сосредоточиться на дорожная карта для 1.1 . Между тем, вы можете написать директиву для реализации настроек фокуса.

Во-вторых, для фокусировки на элементе после того, как он стал видимым, в настоящее время требуется обходной путь. Просто отложите ваш вызов элемента focus () с помощью $timeout.

Поскольку существует та же проблема controller-modizes-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/

6
broc.seib

Простой, который хорошо работает с модалами:

.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 />
4
Shawn Dotey

Если вы просто хотели простой фокус, которым управлял нг-клик.

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
TOBlender

У Марка и Блеша прекрасные ответы; однако у Марка есть недостаток, на который указывает Блеш (помимо того, что он сложен для реализации), и я чувствую, что ответ Блеша содержит семантическую ошибку при создании службы, которая конкретно направляет запрос фокуса на внешний интерфейс, когда на самом деле все, что ему нужно, - это способ отложить событие, пока все директивы не будут прослушаны.

Итак, вот то, что я в итоге сделал, которое во многом отнимает ответ 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);
  }
});
3
joshperry

Это также возможно использовать ngModelController. Работа с 1.6+ (не знаю со старыми версиями).

HTML

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

JS

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

-

N.B .: В зависимости от контекста, вам, возможно, придется обернуться функцией тайм-аута.

N.B.²: При использовании controllerAs это почти то же самое. Просто замените name="myForm" на name="vm.myForm" и в JS vm.myForm.myText.$$element.focus();.

3
Ludovic Guillaume

Вы можете просто создать директиву, которая заставляет сосредоточиться на украшенном элементе на 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"/>

Это будет работать для модальных элементов и переключаемых элементов ng-if, а не для ng-show, поскольку postLinking происходит только при обработке HTML.

3
ibaixas

Наверное, самое простое решение по возрасту ES6.

Добавление следующей директивы liner делает HTML-атрибут autofocus эффективным в Angular.js.

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

Теперь вы можете просто использовать синтаксис автофокуса HTML5, например:

<input type="text" autofocus>
3
Tsuneo Yoshioka

Следующая директива сработала для меня. Используйте тот же атрибут html автофокуса для ввода.

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

Просто новичок здесь, но я был в состоянии заставить его работать в 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 я использовал следующую строку, чтобы указать элемент, на который следует поместить фокус:

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

на шаблоне у меня есть это:

<input id="myInputId" focus />
2
pitervergara

Если вы используете modalInstance и у вас есть объект, вы можете использовать «затем» для выполнения действий после открытия модального. Если вы не используете modalInstance и жестко запрограммированы, чтобы открыть модал, вы можете использовать событие. Тайм-аут $ не является хорошим решением.

Вы можете сделать (Bootstrap3):

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

В modalInstance вы можете посмотреть на библиотеку, как выполнить код после открытия модального.

Не используйте $ timeout, как это, $ timeout может быть 0, 1, 10, 30, 50, 200 или более, это будет зависеть от клиентского компьютера и процесса открытия модального режима.

Не используйте $ timeout, пусть метод скажет вам, когда вы можете сосредоточиться;)

Я надеюсь, что это поможет! :)

2
Filipe Cotrim Melo

Я редактирую директиву 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);
                }
            });
        }
    };
});
2
Mohamad Khani

Весь предыдущий ответ не работает, если требуемый элемент фокуса вставлен в шаблон директивы . Следующая директива соответствует как простому элементу, так и элементу с внедренной директивой (я написал это в TypeScript ). он принимает селектор для внутреннего фокусируемого элемента. если вам просто нужно сфокусировать элемент self - не отправляйте параметр селектора в директиву:

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
Ofir Meguri

Если вы хотите установить фокус на конкретный элемент, вы можете использовать подход ниже.

  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. Позвоните в эту службу.

1
Rakesh Burbure

Я хочу внести свой вклад в эту дискуссию после того, как искал лучшее решение и не нашел его, а вместо этого создал его.

Критерии: 1. Решение должно быть независимым от области действия родительского контроллера для увеличения возможности повторного использования 2. Избегайте использования $ watch для отслеживания какого-либо состояния, поскольку оно медленное, увеличивает размер цикла дайджеста и усложняет тестирование ........ 3. Избегайте $ timeout или $ scope. $ Apply () для запуска дайджест-цикла . 4. Элемент ввода присутствует внутри элемента, в котором используется директива open.

Это решение мне понравилось больше всего:

Директива: 

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

Я надеюсь, что это поможет кому-то там!

1
xiaoma

Это легко .. попробуйте это

HTML

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

JavaScript

document.getElementById("ddl00").focus();
1
isanka thalagala

вы можете использовать директиву ниже, которая получает значение bool в html-вводе, чтобы сосредоточиться на ней ...

//js file
angular.module("appName").directive("ngFocus", function () {
       return function (scope, elem, attrs, ctrl) {
             if (attrs.ngFocus === "true") {
                 $(elem).focus();
             }
             if (!ctrl) {
                 return;
             }
       elem.on("focus", function () {
            elem.addClass("has-focus");
            scope.$apply(function () {
                ctrl.hasFocus = true;
            });
        });
    };
});

<!-- html file -->
<input type="text" ng-focus="boolValue" />

Вы даже можете установить функцию в вашем контроллере на значение директивы ngFocus. Обратите внимание на приведенный ниже код ...

<!-- html file -->
<input type="text" ng-focus="myFunc()" />


//controller file
$scope.myFunc=function(){
      if(condition){
          return true;
      }else{
          return false;
      }
}

эта директива возникает при рендеринге html-страницы. 

0
user7339584

Я думаю, что директива не нужна. Используйте атрибуты HTML id и class для выбора необходимого элемента, а сервис должен использовать document.getElementById или document.querySelector для применения фокуса (или эквивалентов jQuery).

Разметка - это стандартные 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
johans

Не уверен, что полагаться на тайм-аут это хорошая идея, но это работает для ng-repeat, потому что этот код запускается ПОСЛЕ того, как angularjs обновляет DOM, поэтому вы должны убедиться, что все объекты есть:

myApp.directive('onLastRepeat', [function () {
        return function (scope, element, attrs) {
            if (scope.$last) setTimeout(function () {
                scope.$emit('onRepeatLast', element, attrs);
            }, 1);
        };
    }]);
    //controller for grid
    myApp.controller('SimpleController', ['$scope', '$timeout', '$http', function ($scope, $timeout, $http)
    {
        var newItemRemoved = false;
        var requiredAlert = false;
        //this event fires up when angular updates the dom for the last item
        //it's observed, so here, we stop the progress bar
        $scope.$on('onRepeatLast', function (scope, element, attrs) {
            //$scope.complete();
            console.log('done done!');
            $("#txtFirstName").focus();
        });
    }]);
0
Alex

Программно вызывать любое действие над элементом: click (), focus (), select () ...

Использование:

<a href="google.com" auto-action="{'click': $scope.autoclick, 'focus': $scope.autofocus}">Link</a>

Директива:

/**
 * Programatically Triggers given function on the element
 * Syntax: the same as for ng-class="object"
 * Example: <a href="google.com" auto-action="{'click': autoclick_boolean, 'focus': autofocus_boolean}">Link</a>
 */
app.directive('focusMe', function ($timeout) {
    return {
        restrict: 'A',
        scope: {
            autoAction: '<',
        },
        link: function (scope, element, attr) {
            const _el = element[0];
            for (const func in scope.autoAction) {
                if (!scope.autoAction.hasOwnProperty(func)) {
                    continue;
                }
                scope.$watch(`autoAction['${func}']`, (newVal, oldVal) => {
                    if (newVal !== oldVal) {
                        $timeout(() => {
                            _el[func]();
                        });
                    }
                });
            }

        }
    }
});

Для решения этого вопроса установите переменную при инициализации (желательно) в контроллере или как ng-init:

 <input ng-init="autofocus=true" auto-action="{'focus': autofocus}">
0
Mesco

Просто добавляю кофе.

app.directive 'ngAltFocus', ->
    restrict: 'A'
    scope: ngAltFocus: '='
    link: (scope, el, attrs) ->
        scope.$watch 'ngAltFocus', (nv) -> el[0].focus() if nv
0
Talasan Nicholson