angular指令中模板和templateUrl之间的加载顺序差异

时间:2014-03-04 22:43:30

标签: angularjs templates dojo directive

我们几天前就遇到了这个问题。那时,我们将Angular引入基于HTML5的移动家庭照片社交应用程序Family Snap。它由www.uhella.com维护。

在重组期间,我将dojo代码移动到指令内联,它运行良好。 calendar_month_datepicker (dojox.mobile.SpinWheelDatePicker)被dijit成功注入,成为一个巨大的Div。

之后,我想把它分成单独的html文件作为模板,因为html编辑器会更好地理解我的html代码。所以我修改代码如下:

Familysnap /指令/ homepickdata.js

'use strict';
/* Directives */
FamilySnapModule.directive('homePickdata', function() {
    return  {
        restrict: 'EAC',
        replace: true,
        transclude: true,
        templateUrl: 'Familysnap/templates/homePickdata.html'
        //template: '<div id="calendar_month_datepicker" data-dojo-type="dojox.mobile.SpinWheelDatePicker" data-dojo-props=\'slotOrder: [0,1,2], monthPattern: "MM", dayPattern: "dd", align: "center"\'></div>'
        };
});

Familysnap /模板/ homePickdata.html

<div id="calendar_month_datepicker" data-dojo-type="dojox.mobile.SpinWheelDatePicker" data-dojo-props='slotOrder: [0,1,2], monthPattern: "MM", dayPattern: "dd", align: "center"'></div>

Familysnap /模块/ dataPicker.js

 require([
    …
             ], function(dom, domStyle, domAttr, on, ready, registry, JSON, string,
                         ListItem, array, request, domClass, query, domProp, domConstruct, tap, swipe, Uuid, generateRandomUuid,
                         Pane, SpinWheelDatePicker, win, Opener, Heading, ToolBarButton, SwapView) {        


    function FamilySnapMonthToday()
    {
        …

        setTimeout(function(){

        registry.byId("calendar_month_datepicker").set("values", [global_calendar_current_year, global_calendar_current_month + 1, global_calendar_current_date]);
    }, 500);
    …
}

function FamilySnapMonthDone()
{…

    var values = registry.byId("calendar_month_datepicker").get("values");
 …
}

ready(function(){
…
        on(dom.byId("calendar_month_done_btn"), "click", FamilySnapMonthDone);
    …
    });
});

本变形例后,在 calendar_month_datepicker (适用的 dojox.mobile.SpinWheelDatePicker )不是由注入的dijit。它只是由角度编译器注入。 并且“ registry.byId(”calendar_month_datepicker“)”将始终返回null。

我终于弄明白模板和templateUrl之间的加载顺序在角度编译器中是由chrome源代码调试工具(Debugging-in-PhoneGap)不同。

首先,我在我的指令上设置了断点。

当时代码暂停在我的断点上。

Familysnap /指令/ homepickdata.js

'use strict';
/* Directives */
FamilySnapModule.directive('homePickdata', function() {

返回{

restrict: 'EAC',
            replace: true,
            transclude: true,
            templateUrl: 'angular/templates/homePickdata.html'
            //template: '<div id="calendar_month_datepicker" data-dojo-type="dojox.mobile.SpinWheelDatePicker" data-dojo-props=\'slotOrder: [0,1,2], monthPattern: "MM", dayPattern: "dd", align: "center"\'></div>'
            };
    });

两个版本中的指令“home-pickdata”未注入。这就是我们的期望。

<div home-pickdata></div>

不同之处在于:

function bootstrap(element, modules) {
  var doBootstrap = function() {
    element = jqLite(element);

    if (element.injector()) {
      var tag = (element[0] === document) ? 'document' : startingTag(element);
      throw ngMinErr('btstrpd', "App Already Bootstrapped with this Element '{0}'", tag);
    }

    modules = modules || [];
    modules.unshift(['$provide', function($provide) {
      $provide.value('$rootElement', element);
    }]);
    modules.unshift('ng');
    var injector = createInjector(modules);
    injector.invoke(['$rootScope', '$rootElement', '$compile', '$injector', '$animate',
       function(scope, element, compile, injector, animate) {
        scope.$apply(function() {
          element.data('$injector', injector);

编译(元素)(范围);

        });
      }]
    );
    return injector;
  };

在编译(元素)(范围)之后,指令的模板版本注入如下:

<div id="calendar_month_datepicker" data-dojo-type="dojox.mobile.SpinWheelDatePicker" data-dojo-props='slotOrder: [0,1,2], monthPattern: "MM", dayPattern: "dd", align: "center"'></div>

但是templateUrl版仍然是:

<div home-pickdata></div>

即使在angularInit之后:

 //try to bind to jquery now so that one can write angular.element().read()
  //but we will rebind on bootstrap again.
  bindJQuery();

  publishExternalAPI(angular);

  jqLite(document).ready(function() {
    angularInit(document, bootstrap);
  });

})(window, document);

templateUrl版本仍然是:

<div home-pickdata></div>

在此钩子之后,dojo注入器将处理所有dojo标记, 但那时,Angular还没有注入templateUrl版本的指令。

所以dojo / dijit不知道ID“ calendar_month_datepicker ”。 这解释了为什么registry.byId(“calendar_month_datepicker”)在我们的代码中返回NULL。

我不熟悉dojo注入器。我相信有一些方法可以通过一些魔法使dojo与angular templateUrl指令一起工作。

通过阅读Dimitri M和tik27的答案,我更新了代码。 我们需要手动调用“dojo / parser”来注入我们的小部件。

将数据 - 道场 - 类型更改为数据 - familysnap -type。

<div id="calendar_month_datepicker" data-family-type="dojox.mobile.SpinWheelDatePicker" data-dojo-props='slotOrder: [0,1,2], monthPattern: "MM", dayPattern: "dd", align: "center"'></div>

并在ready()

上调用解析器
require(["dojo/parser"],function(dom,registry,parser)){

        ready() {
    parser.parse({scope: "familysnap"});
    ...
        }
}

然后dijit注入了calendar_month_datepicker。 我们可以成功致电

registy.byId('calendar_month_datepicker')

0 个答案:

没有答案