【问题标题】:AngularJS - Load Controller asynchronously From AJAX Without Changing RouteAngularJS - 从 AJAX 异步加载控制器而不更改路由
【发布时间】:2017-06-17 03:29:55
【问题描述】:

我想在渲染新视图 (HTML) 的 ajax 调用时动态加载角度控制器。

这是我所拥有的:

视图示例。来自 AJAX 的 HTML 片段

    <!-- CVS Pharmacy Extracare - Add View -->

<div ng-controller="cvsViewCtrl" class="container-fluid">
  <div class="col-md-8 col-md-offset-2">
    <h3 id="asset-title" class=""></h3>
    <br>
    <p>Member ID</p>
    <input class="input-s1 block-elm transition" type="text" placeholder=""/>
    <br>

    <input class="add-asset-btn btn btn-success block-elm transition" type="button" value="Add Asset!" ng-click="prepareCVS();"/>
  </div>
</div>

与视图相关的单独脚本

App.controller('cvsViewCtrl', ['$scope', '$http', function($scope, $http){
    console.log('cvs view loaded');

    $scope.prepareCVS = function() {
      console.log('admit one');
    }
  }]);

以及加载它们的函数

$scope.setAddAssetView = function(a) {
      console.log(a);

      if($scope.currentAddView == a) {
        console.log('view already set');
        return;
      }

      $scope.currentAddView = a;

      $('#main-panel').html('');
      $http({
        method: 'POST',
        url: '/action/setaddassetview',
        headers: {
          'Content-Type': 'application/json',
        },
        data: {
          asset: a,
        }
      }).then(function(resp){
        // Success Callback
        // console.log(resp);
        var index = resp.data.view.indexOf('<s');
        var script = resp.data.view.slice(index);
        var html = resp.data.view.replace(script, '');

        $('#main-panel').html( html );
        $('#asset-title').text(a.name);

        var indexTwo = a.view.indexOf('/add');
        var scriptLink = insertString(a.view, indexTwo, '/scripts').replace('.html', '.js').replace('.', '');
        console.log( scriptLink );
        window.asset = a;

        $.getScript(scriptLink, function(data, textStatus, jqxhr){
          console.log('loaded...');
        })

      },
      function(resp){
        // Error Callback
        console.log(resp);
      });
    }

当 $.getScript 运行时,脚本会成功加载,但不会初始化控制器。我什至试过:

var s = document.createElement('script');
s.type = 'text/javascript';
s.src = scriptLink;
s.innerHTML = null;
s.id = 'widget';

document.getElementById('switch-script').innerHTML = '';
document.getElementById('switch-script').appendChild( s );

这会附加带有正确链接的脚本,但仍未初始化。我该如何解决这个问题?

【问题讨论】:

    标签: javascript jquery html angularjs ajax


    【解决方案1】:

    在您的应用程序中进行此更改,并确保在呈现带有 ng-controller 的 html 之前加载控制器文件。

    var App = angular.module("app", [...]);
    
    App.config(["$controllerProvider", function($controllerProvider) {
    
        App.register = {
            controller: $controllerProvider.register,
        }
    
    }]);
    
    App.register.controller('cvsViewCtrl', ['$scope', '$http', function($scope, $http){
        console.log('cvs view loaded');
    
        $scope.prepareCVS = function() {
          console.log('admit one');
        }
    }]);
    

    【讨论】:

    • 谢谢!会试试这个。哪个部分在单独的控制器文件中?还是他们都在主应用程序文件中?
    • @ryanwaite28 , 其实你的 App 定义和 App.config 都在你的 app.js 文件里,你可以把你的 cvsViewCtrl 代码放在任何文件里!
    • 它实际上对我不起作用(我可能做得不对)但是谢谢!我会再试一次。实际上,我找到了一种替代我的情况的方法,到目前为止效果很好。谢谢!
    【解决方案2】:

    这实际上不是处理事情的正确方式。

    如果你使用 ui-router 进行路由,你可以在 resolve 函数中加载控制器。一个很好的服务是ocLazyLoad

    可以这样做:

    var app = angular.module('myApp', [
        'ui.router',
        'oc.lazyLoad',
    ]);
    
    angular.module('myApp').config(function($stateProvider, $urlRouterProvider) {
    
        $urlRouterProvider.otherwise('/login');
        $stateProvider
            .state('main', {
                url: '/main',
                templateUrl: 'app/views/main.view.html',
                controller: 'mainCtrl',
                resolve: {
                    loadCtrl: ['$ocLazyLoad', function($ocLazyLoad) {
                        return $ocLazyLoad.load('app/ctrls/main.ctrl.js');
                    }],
                }
            })
            .state('second', {
                url: '/second',
                templateUrl: 'app/views/second.view.html',
                controller: 'secondCtrl',
                resolve: {
                    loadCtrl: ['$ocLazyLoad', function($ocLazyLoad) {
                        return $ocLazyLoad.load('app/ctrls/controller_TWO.ctrl.js');
                    }],
                }
            })
    
    });
    

    当您从一个路由更改为另一个路由时,将在加载 html 之前触发解析并正确注册控制器。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2014-02-03
      • 1970-01-01
      • 2013-03-24
      • 1970-01-01
      • 1970-01-01
      • 2017-05-22
      • 1970-01-01
      相关资源
      最近更新 更多