Dojo 1.8:在呈现自定义模板时获取 dest.appendChild 不是函数

Posted

技术标签:

【中文标题】Dojo 1.8:在呈现自定义模板时获取 dest.appendChild 不是函数【英文标题】:Dojo 1.8: Getting dest.appendChild is not a function while rendering a custom template 【发布时间】:2012-10-24 01:30:50 【问题描述】:

添加 WidgetsInTemplateMixin 后,我收到一个错误

dest.appendChild is not a function

在文档中,它声称如果 this.containerNode 不能包含任何子对象,则会出现错误。但是,我已经为具有 dojo 类型“dijit/layout/ContentPane”的 div 标记了 containerNode 连接点。谁能向我解释为什么这不起作用?

这是模板文件

<div class="$baseClass">
    <div class="$baseClassContainer"
         data-dojo-type="dijit/layout/BorderContainer"
         data-dojo-props="design: 'headline'">
        <div data-dojo-type="dijit/layout/ContentPane"
             data-dojo-props="region: 'top'">
            Top
        </div>
        <div data-dojo-type="dijit/layout/ContentPane"
             data-dojo-props="region: 'center'"
             data-dojo-attach-point="containerNode">
        </div>
        <div data-dojo-type="dijit/layout/ContentPane"
             data-dojo-props="region: 'leading', splitter: true">
            Sidebar
        </div>
    </div>
</div>

这里是javascript定义

define([
    "dojo/_base/declare",
    "dijit/_WidgetBase",
    "dijit/_OnDijitClickMixin",
    "dijit/layout/BorderContainer",
    "dijit/layout/ContentPane",
    "dijit/layout/TabContainer",
    "dijit/_TemplatedMixin",
    "dijit/_WidgetsInTemplateMixin",
    "dojo/text!./templates/MainContainer.html"
], function (declare,
             _WidgetBase,
             _OnDijitClickMixin,
             BorderContainer,
             ContentPane,
             TabContainer,
             _TemplatedMixin,
             _WidgetsInTemplateMixin,
             template)


    return declare([_WidgetBase, _OnDijitClickMixin, _TemplatedMixin, _WidgetsInTemplateMixin], 

        templateString:template,
        baseClass:"main"
    );

);

以声明方式定义的自定义小部件

<div data-dojo-type="main/ui/MainContainer" data-dojo-props="title: 'Main Application'">
  Hello Center!
</div>

【问题讨论】:

【参考方案1】:

您的问题值得研究。 appendChild 方法仅适用于 DOM 节点。根据源码,containerNode 必须是一个 DOM Node。

dijit/_TemplatedMixin.js

 _fillContent: function(/*DomNode*/ source)
    // summary:
    // Relocate source contents to templated container node.
    // this.containerNode must be able to receive children, or exceptions will be thrown.
    // tags:
    // protected
    var dest = this.containerNode;
        if(source && dest)
            while(source.hasChildNodes())
            dest.appendChild(source.firstChild);
        
    
, 

看看这个 dijit/_WidgetBase.js。注释显示containerNode的类型是DomNode

// containerNode: [readonly] DomNode
//      Designates where children of the source DOM node will be placed.
//      "Children" in this case refers to both DOM nodes and widgets.
//      For example, for myWidget:
//
//      |   <div data-dojo-type=myWidget>
//      |       <b> here's a plain DOM node
//      |       <span data-dojo-type=subWidget>and a widget</span>
//      |       <i> and another plain DOM node </i>
//      |   </div>
//
//      containerNode would point to:
//
//      |       <b> here's a plain DOM node
//      |       <span data-dojo-type=subWidget>and a widget</span>
//      |       <i> and another plain DOM node </i>
//
//      In templated widgets, "containerNode" is set via a
//      data-dojo-attach-point assignment.
//
//      containerNode must be defined for any widget that accepts innerHTML
//      (like ContentPane or BorderContainer or even Button), and conversely
//      is null for widgets that don't, like TextBox.
containerNode: null,

因此,containerNode 被设计为 DomNode,而不是错误。它不能是一个小部件。也许你应该尝试一些其他的方法。

更新: 在自定义小部件中添加一些 BorderContainers

ModuleWithGuideBar.html

<div data-dojo-attach-point="containerNode" class="$class ModuleWithGuideBar">
    <div class="ModuleGuideBar"
         data-dojo-type="dijit.layout.BorderContainer"
         data-dojo-props="region:'top', gutters:false"
         data-dojo-attach-point="guideBarFirst">
    </div>
    <div class="ModuleGuideBar"
         data-dojo-type="dijit.layout.BorderContainer"
         data-dojo-props="region:'top', gutters:false"
         data-dojo-attach-point="guideBarSecond">
    </div>
    <div class="ModuleContent"
         data-dojo-type="dijit.layout.BorderContainer"
         data-dojo-props="region:'center', gutters:false, liveSplitters:false"
         data-dojo-attach-point="moduleContent">
    </div>
</div>

js文件

define([
    "dojo/_base/declare",
    "dijit/layout/BorderContainer",
    "dijit/_TemplatedMixin",
    "dijit/_WidgetsInTemplateMixin",
    "dojo/text!./templates/ModuleWithGuideBar.html"

], function (declare, BorderContainer, TemplatedMixin, _WidgetsInTemplateMixin, template) 
    return declare("common.widget.ModuleWithGuideBar", [BorderContainer, TemplatedMixin, _WidgetsInTemplateMixin], 
        templateString:template,
        region:"center",
        gutters:false,
        guideBarFirst:null,
        guideBarSecond:null,
        moduleContent:null
    );
);

【讨论】:

我通过添加带有附加点的 div 让它工作,但它似乎没有正确解析边界容器。我确实可以提起模板并将其放入我的文件中,并且它可以正常工作,但是当它解析它时,边框容器没有正确绘制。知道为什么会这样吗? 如果自定义小部件中有一些 BorderContainers,您可以混入 dijit/_LayoutWidget。但是你必须定义你自己的 layout() 方法,来管理内部的 BorderContainers。我找到了一个简单的方法来做到这一点。查看更新后的答案。【参考方案2】:
define([
//...
    "dijit/_WidgetBase"

然后

return declare('YourWidget',[_WidgetBase , _TemplatedMixin, _WidgetsInTemplateMixin],
     templatePath: 'local/to/your/template.html',
     widgetsInTemplate: true,
     //...

然后

var yourWidget= new YourWidget(,'YourWidgetNodeId'); 

【讨论】:

以上是关于Dojo 1.8:在呈现自定义模板时获取 dest.appendChild 不是函数的主要内容,如果未能解决你的问题,请参考以下文章

以自定义表单呈现模板中的各个字段

Dojo 1.8 构建系统 - 如何设置前缀/路径?

Dojo 1.8 图表编程教程报错

Django 自定义模板标签抛出错误

Django 1.8 没有使用我的自定义登录页面

在自定义模板标签中解析 Django 自定义模板标签