用角度加载部分页面并编译控制器



在大规模应用程序中,我们的Web应用程序可能会被组织成单独的部分页面,以增加应用程序的模块化。在某些情况下,通过XHR加载的部分页面或使用Angular $ http.get或jquery $。负载的部分页面会引入错误。

以我的方案为例,我正在使用Kohana PHP框架,以便我可以在服务器级别上控制Web应用程序的模块化。像往常一样,所有模板和页面都被分开,将所有HTML,JS和CSS放在演示层上。

这将为我提供极大的灵活性,可以在客户端处理上实现JavaScript MVW/MVC堆栈,因为我的Web应用程序在很大程度上取决于Ajax请求以从后端应用程序获取数据。在我的方案中,我使用angularjs及以下是一个简单的伪伪,介绍了从模型显示向客户端的数据。

kohana模型> kohana控制器> kohana视图> xhr> jquery angular> dom

我在应用程序中的一部分之一,它确实使我颠簸,让我喝几瓶代谢饮料来解决该应用程序。是我有模态对话框的地方,部分页面是通过服务器从XHR加载的,并将其连接到选定的DOM。

问题是,当Angular尝试编译部分页面时,当它找到NG-Controller指令时,它将寻找参考已处理指令的函数。由于尚未通过DOM解析器评估控制器,因此出现了误差。但是,当您在加载部分页面之前的应用程序中的某个地方预先放置功能时,一切都可以。下面是我如何设置对话框服务的示例

var dialogService = angular.module('dialog.service', []);
dialogService.factory('Dialog', function($http,$compile){
    var dialogService = {};
    dialogService.load = function(url, scope){
        $("#dialog:ui-dialog").dialog( "destroy" );
        $("#dialog").attr('title','Atlantis');
        $http.get(url).success(function (data) {
            html = $compile(data)(scope);
            $('#dialog-content').html(html);
            $("#dialog").dialog({
                width: '600px',
                buttons: {
                    "Ok": function() {
                        $( this ).dialog( "close" );
                        return true;
                    },
                },
                close: function(){
                    if (typeof (onClose) == 'function') { onClose(); }
                },
            });
        });
    }
    return dialogService;
});

经过一项研究,我找到了一些解决方案,并与伙计分享了我的回答,就像我像我一样的初学者。(对不起,我的英语)。

此设置上的Angularjs上没有错,其他JS Guru可能已经知道解决方案,并且在发明另一种酷炫的Web开发工具或框架时非常忙于与我们分享。可以继续这样做。这可能不是一个很酷的解决方案,也不是最后通式解决方案,请与我们分享任何改进或提示!

要克服这个问题,我们需要S设置策略,让我从示例代码开始,以便我们的大脑在信息流通过时消化。下面的代码是占位符,我使用jQuery创建"模态对话框",并且AJAX内容将被插入。

<div ng-app="asng" id="dialog" title="" style="display:none">
     <div id="dialog-content"></div>
</div>

作为基本知识,我们必须了解DOM解析器的工作原理。我们可能会认为DOMP(DOM解析器)是一个多线程,这就是我们可以并行加载多个外部资源的原因。实际上,DOMP是单线螺纹,同时从上到下解析DOM元素索引。以下是部分页面上的示例,我将加载到#Dialog-contog-contentdiv元素中。

<script language="JavaScript" type="text/javascript">
    function Transaction ($scope,$http){
        $scope.items = [{"country":"VN","quantity":"100"}];
        $scope.country_name = $scope.items;
    }
</script>
<style>
</style>
<div id="transaction-panel" class="user" data-ng-controller="Transaction">
        <form id="{{ form_name }}" action="">
        Country : [[ items.country ]] </br>
        Total : [[ items.quantity ]]
    </form>
</div>

实际上,这些部分仍会出现错误,尽管我们已使用NG-Controller指令将脚本块放在元素之前。实际上,事实并非如此,我们需要解决的部分是AngularJS编译服务如何编译部分DOM。放回上面的我的问题部分,检查我们进行编译的行在哪里。

html = $compile(data)(scope);
$('#dialog-content').html(html);

上面的第一行将在数据变量中编译DOM,不幸的是,将第一行插入root dom将大喊错误:找不到控制器事务。

发生这种情况是因为,DOMP解析器尚未评估部分页面中的脚本块,因为未插入根DOMP中。现在,您可以看到灯光确定,因此我们必须通过插入新DOM来稍微更改编译策略,然后我们将解析下面的插入的DOM外观示例: -

html = $('#dialog-content').html(data);
$compile(html)(scope);

苗条而简单的解决方案,我花了几个人的早晨才能解决这个问题,只是因为忽略了DOM解析的简单概念。

如果我了解您要做的事情,这是一个简单的示例。

我想通过ajax发布到django表单,然后用返回的标记替换页面中的表单内容。返回的标记包括一个ng-controller,我需要在加载时执行它:

.controller('MyForm', function($element, $compile, $scope){
    var scope = $scope;
    var $theForm = $element;
    var $formBlock = $element.find('.the_form');  // is replaced by the form response
    $element.find('.submit_the_form').click(function(){
        // submit the form and replace contents of $formBlock
        $.post($theForm.attr('action'), $theForm.serialize(), function(response){
            var newstuff = $formBlock.html(response);
            $compile(newstuff)(scope); // loads the angular stuff in the new markup
        });
    });
})

我认为您感兴趣的行是$ compile(newstuff)(范围);

编辑:克里基(Crikey)今天早上尝试了其他一些标记,但我无能为力,我无能为力。事实证明,如果我在新标记中没有分配NG模型的字段,则$编译将不会执行。添加:

<input type="hidden" name="dummy" value="0" ng-model="dummy"/>

...现在它编译了。

最新更新