iframe中的表单无法通过Angular和IE11重新获得焦点

时间:2015-08-14 16:38:52

标签: javascript angularjs internet-explorer iframe angularjs-directive

我有一个Angular应用程序,其中包含一个包含iframe的路径。 iframe加载表单。在第一次加载路径时,您可以在表单中输入数据。在路径的第二次加载时,表单输入无法重新关注IE11中的单击。适用于Chrome和Firefox。

重新创建的具体步骤如下:

  1. 在IE11中加载页面
  2. 点击iframe链接
  3. 可以将数据输入表格输入
  4. 当光标仍在表单输入中时,单击Iframe链接
  5. 路线将重新加载,清除表格
  6. 单击表单输入以输入新文本时,表单无法重新获得焦点
  7. 我注意到如果您在输入文字后点击“主页”链接,然后点击iframe链接,表单就可以重新获得焦点,从而允许输入新文本。

    以下是重新创建问题的示例代码。你可以看到它在这里运行:http://matthewriley.github.io/iframe-form/

    请注意,控制器会根据标志强制重新加载路径。这是为了支持业务要求,即如果用户在iframe中并选择单击iframe链接,则路由将完全重新加载。

    是什么原因导致IE11阻止iframe中的表单重新关注第二次加载?

    HTML页面

    <!DOCTYPE html>
    <html lang="en-US">
        <head>
            <meta charset="utf-8" />
            <title>Iframe Reload Test</title>
        </head>
        <body>
            <div ng-app="IframeTest">
                <p><span><a href="#/">Home</a></span>&nbsp;<span><a href="#/iframe">Iframe</a></span></p>
                <div ui-view></div>
            </div>
            <script src="//cdnjs.cloudflare.com/ajax/libs/angular.js/1.4.3/angular.min.js"></script>
            <script src="//cdnjs.cloudflare.com/ajax/libs/angular-ui-router/0.2.15/angular-ui-router.min.js"></script>
            <script src="app.js"></script>
        </body>
    </html>
    

    Angular App

    // app.routes.js
    (function() {
        'use strict';
        angular
            .module('IframeTest', [
                'ui.router',
                'IframeTest.iFrameModule'
            ])
            .config(routeConfig);
        routeConfig.$inject = ['$stateProvider', '$urlRouterProvider'];
        function routeConfig($stateProvider, $urlRouterProvider) {
            $urlRouterProvider.otherwise("/");
            $stateProvider
                .state('home', {
                    url:'/',
                    template: '<h4>Home</h4><p>This is the home page.</p>'
                })
                .state('iFrame', {
                    url:'/iframe',
                    template: '',
                    controller: 'IFrameCtrlAs',
                    controllerAs: 'vm'
                })
                .state('iFrame/:flag', {
                    url:'/iframe/:flag',
                    template: '<h4>Iframe</h4><p><iframe src="{{vm.url}}" id="iframeID" frameborder="1" width="100%" scrolling="no"></iframe></p>',
                    controller: 'IFrameCtrlAs',
                    controllerAs: 'vm'
                });
        }
    })();
    
    // iFrame.controller.js
    (function() {
        'use strict';
        angular
            .module('IframeTest.iFrameModule', [])
            .controller('IFrameCtrlAs', IFrameCtrlAs);
        IFrameCtrlAs.$inject = ['$stateParams', '$location'];
        function IFrameCtrlAs($stateParams, $location) {
            var vm = this;
            if(!angular.isDefined($stateParams.flag)){
                var reloadPath = $location.path() + '/true';
                $location.path(reloadPath);
            }
            else{
                vm.url = 'form.html';
            }
        }
    })();
    

    iframe中的表单

    <form method="post" action="">
        <input type="text" id="example1" name="example1" placeholder="sample text">
    </form>
    

1 个答案:

答案 0 :(得分:8)

我不知道是什么导致了这个问题,可能是IE怪癖。 无论如何,我发现如果你手动将iframe集中在JS中,但它必须在$timeout中才能正常工作。

我在iframe中添加了一个ng-init,它基本上是手动聚焦iframe。

.state('iFrame/:flag', {
        url:'/iframe/:flag',
        template: '<h4>Iframe</h4><p><iframe src="{{vm.url}}" ng-init="vm.init()" id="iframeID" frameborder="1" width="100%" scrolling="no"></iframe></p>',
        controller: 'IFrameCtrlAs',
        controllerAs: 'vm'
    });

这是控制器

function IFrameCtrlAs($stateParams, $location, $timeout) {
    var vm = this;

    if(!angular.isDefined($stateParams.flag)){
        var reloadPath = $location.path() + '/true';
        $location.path(reloadPath);
    }
    else{
        vm.url = 'form.html';

    }
    vm.init = function(){
            $timeout(function(){        
                document.getElementById("iframeID").contentWindow.focus();
                console.log("loaded")
            })
    }
}

当然,将它包装在指令中可能更清晰。