【问题标题】:Angular ui-bootstrap-tpls-0.12.1 Open modal Dialog Set focusAngular ui-bootstrap-tpls-0.12.1 打开模态对话框设置焦点
【发布时间】:2015-05-02 07:45:09
【问题描述】:

我目前正在玩 angular,尤其是 angular 和 bootstrap 模块(现在没有 bootstrap 谁能活下去?)。

在任何情况下,是否有人有一个干净的解决方案来将焦点设置在弹出打开的新模式对话框中的输入字段上? 开箱即用似乎不支持此基本功能。 我以为我可以在“开放”的未来上钩——但它似乎很早就被召唤了。

所以,当您打开一个模态实例时 - 例如

$modal.open({
                "templateUrl": 'myModalContent.html',
                "controller" : 'modalInstanceCtrl',
                "size": size,
                "resolve" : {
                    "items": function () {
                        return $scope.items;
                    }
                }
            });

然后您可以将模态实例与广播偶数之类的东西一起使用:

 modalInstance.opened.then(function(){
                $rootScope.$broadcast(myNewDirectiveBootstrapConfig.events.modalInstanceOpened
                        , modalInstance);
            });

现在我要关注的输入元素将使用指令进行角度增强。

<label for="popupTitle">Title:</label>
<input type="text" class="form-control" id="popupTitle"
       ng-required="true"
       ng-model="popup.title"
       ng-minlength="1"
       newdirective-modal-focus
       >

指令代码不会是侵入性的,并且独立于页面逻辑。理想情况下,您只会使用事件 API,然后调用您的非侵入式指令并执行焦点魔术。

angular.module('newDirectivesModule', [])
.constant('myNewDirectiveBootstrapConfig', {
    events: {
        modalInstanceOpened : "modalInstanceOpened"
    }
})
.directive('newdirectiveModalFocus', ['myNewDirectiveBootstrapConfig',    
function (myNewDirectiveBootstrapConfig) {
    return {
      restrict:'A', // process compile directive only on element attributes


       link: function(scope, elm, attr) {             
             scope.$watch(function(){return elm.is(":visible");}, function(value) {
                 if(elm.is(":visible")){
                     elm.focus();                         
                 }                   
             });

             scope.$on(myNewDirectiveBootstrapConfig.events.modalInstanceOpened, function(event, data) {
                 if(elm.is(":visible")){
                     elm.focus();
                 }                   
             });                                  
        }          
    };
}]);

您在代码中看到了我使用不同的手表场景玩过的代码。 现实是,指令代码被调用给儿子。 opens.then 未来似乎正在发布事件,说明模型在您实际看到浮动在屏幕上的模态对话框之前已打开。 输入元素被告知设置为焦点 - 但很快,如果我调试它在调用 focus() 时仍然在后台。 IT 是可见的,从某种意义上说,您可以在页面的 dom 中进行查找,并且从某种意义上说,如果您询问 JQuery(":visible") dom 元素,它确实是可见的。但它仍然是肉眼看不见的。

我在其他地方看到了一种与我完全不同的方法,它不依赖于事件并且依赖于从真到假的属性值。 我根本不喜欢这种方法,因为它与页面的业务逻辑过于耦合,我不喜欢并拒绝将其作为解决方案。

对此的解决方案应该完全依赖于这样一个事实,即模态对话框的主体中只有一个输入元素,该元素带有 set focus on me please 指令,并尽可能与页面逻辑分离。

理想情况下,这应该是 bootsrap angular 本身支持的功能,遗憾的是它似乎不是,但由于我们必须 - 在任何情况下 - 使用 API 来打开对话框并关闭它们,我们应该能够扩展这一步以横切干净的方式获得焦点功能。

对此有何建议?

【问题讨论】:

    标签: javascript angularjs twitter-bootstrap focus


    【解决方案1】:

    我对焦点 post link 使用不同的指令方式来确保渲染元素(无论是否为模态):

    app.directive('focusMe',
        ['$timeout',
            function ($timeout) {
                return {
                    link: {
                        pre: function preLink(scope, element, attr) {
                          // ...
                        },
                        post: function postLink(scope, element, attr) {
                            $timeout(function () {
                                element[0].focus();
                            }, 0);
    
    
                        }
                    }
                }
            }]);
    

    所以输入应该是这样的:

    <input type="text" 
           focus-me
           class="form-control" id="popupTitle"
           ng-required="true"
           ng-model="popup.title"
           ng-minlength="1">
    

    Plunker

    中的演示

    【讨论】:

    • 您好,我同意您的建议,但我认为解决方案并不完美。您提供的解决方案在您的测试页面中很有效。在我的身上,我不得不设置 200 毫秒的超时时间。超时 0 没有正常工作,在你的例子中,我调试了 example.js,当你在元素上设置 focus() 时,模态仍然不可见。我想知道你是否在时机上走运。因为最有可能在我身上 - 在我设置焦点的时间和模态实际上完全可见的时间之间焦点会发生变化。在焦点函数和 c 上设置断点。
    • 因为在我的情况下,我不得不设置 200 毫秒的超时时间,我当然不喜欢这个解决方案,因为它不是确定性的行为。我会尝试看看当我的遭受焦点()但没有关注时,我是否找出最终获得焦点的元素。其他人必须得到它 - 例如提交按钮等。我会... 但我喜欢我可以放弃这个事件的事实,所以你的解决方案比我的要简单得多。这总是很好。越简单越好。
    • @99Sono 你尝试使用$timeout 没有价值吗?喜欢:$timeout(function () { element[0].focus(); });
    • @99Sono 问题是你如何渲染模式?你能改变我提供的 plunker 重现问题吗?
    • 根据 boostrap 文档中的 sn-p,我非常像您一样打开模型。我在我的 sn-p 中添加了一些虚拟的额外数据模型(“项目”),但在你的情况下,即使使用 ng-repeat,焦点也很好。我在补丁中有其他组件,例如角树。不,我将分析我的页面。无论如何,如果你的超时设置为 0,为什么还需要使用超时服务呢?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-12-14
    • 1970-01-01
    • 1970-01-01
    • 2020-04-11
    • 2016-11-20
    • 1970-01-01
    • 2012-12-23
    相关资源
    最近更新 更多