2013-12-18 3 views
1

У меня есть загрузочные вкладки Bootstrap, каждая из которых содержит текстовое поле. Я настроил его так, чтобы вы могли создавать новые вкладки, содержащие текстовые поля. Однако, когда эта новая вкладка создана, я хочу, чтобы в ней была сосредоточена текстовая область с помощью курсора.Фокус Новая вкладка Textarea Bootstrap 3 + AngularJS

Вот соответствующий код проблемы со слегка большей скрипкой, показывающей его в действии: http://jsfiddle.net/HB7LU/1390/ Для скрипки он должен сфокусировать текстовое поле после создания первого элемента.

function ListController($scope, topics) { 

    var currentId = 0; 
    $scope.mainList = topics; 

    $scope.addItem = function() { 
     topics.push({ 
      id: (currentId++), 
      active: "active", 
      name: $scope.newItem, 
     }); 

     //clears input box 
     $scope.newItem = ""; 

     //remove previous bootstrap active classes 
     $('ul.nav-pills li.active').removeClass('active'); 
     $('.tab-content .tab-pane.active').removeClass('active'); 

     //Can't get this part to work!! 
     //(the textareas have dynamic id's) 
     $('#textarea0').focus(); 
    } 
} 

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

ответ

1

Угловой рекомендует вам не выполнять манипуляции с DOM внутри контроллеров. Линия здесь размыта, так как вы технически выполняете манипуляции в директиве, но используете функцию контроллера для ее выполнения. Я лично избегу этого.

В любом случае, одно из преимуществ этого в директиве - предоставить вам легкий доступ к element. И это упрощает использование jQlite, который является Angular aware vs jQuery.

Так что я бы удалить эту строку в контроллере, который вызывает вам неприятность: $('#textarea0').focus();

И, вместо того, чтобы добавить эту jQlite строку в директиву:

angular.element(document.querySelector('#textarea0')).focus(); 

Так что ваша директива теперь выглядит следующим образом :

myApp.directive('ngEnter', function ($timeout) { 
    return function (scope, element, attrs) { 
     element.bind("keydown keypress", function (event) { 
      if(event.which === 13) { 
       scope.$apply(function(){ 
        scope.$eval(attrs.ngEnter); 
       }); 
       angular.element(document.querySelector('#textarea0')).focus(); 

       event.preventDefault(); 
      } 
     }); 
    }; 
}); 

Это решает проблему: updated fiddle

Но я бы также переместил две строки removeClass в вашу директиву и вместо этого использовал jQlite - если бы это был я. Тогда ваша функция контроллера может сфокусироваться на задачах, связанных с списком, в то время как директива обрабатывает DOM.

+0

Я ценю ваше понимание лучшей практики углов. Я только начал использовать Angular, так что это был очень полезный ответ. Единственная проблема с этим решением заключается в том, что, поскольку я динамически идентифицирую textarea при создании, я должен выбрать их с помощью $ ('# textarea' + currentId), а currentId - в контроллере. Я, очевидно, могу переместить его за пределы контроллера и дать ему более широкий охват, но для меня это не так, и, вероятно, это не самая лучшая практика. Есть ли лучший, более Угловой способ решить эту проблему? – Chris

+0

Если я буду следовать за вами, вы можете добавить 'addItem'' currentId', поэтому он будет доступен внутри вашей директивы для использования в 'querySelector()' – KayakDave

+0

Вот пример этого: http://jsfiddle.net/HB7LU/1397/(я не использовал currentId- но вы увидите, как возвращается возвращаемое значение) – KayakDave

Смежные вопросы