2012-03-28 40 views
1

我想完成一个模块,我需要使用嵌套模板,我卡在如何可以做到这一点。在JavaScript/jQuery/AJAX嵌套模板

基本上在我的用户界面中有3个级别,例如说1级,2级,3级。 所以当页面显示时,我只需要渲染级别1。 但是当用户点击level1的任何元素的“展开”按钮时,我需要呈现级别1的选定元素下的级别2(不是全部)的相应元素。

现在,当用户点击“展开”级别2的元素,相应的级别3应呈现..

总结它应该就像Windows资源管理器的左侧导航栏。

+1

看看我的更新答案... – 2012-03-28 11:49:43

+0

根本真棒.. !!!再次感谢.. – 2012-03-28 13:04:29

回答

1

通常,您应该为每个级别定义单独的组件,为每个组件分配模板并实施类似expand()/collapse()方法。如果一个组件最初被折叠(你的情况),那么它不应该在初始化时渲染子项目,它只会在展开它们时才会渲染它们(将使用适当的子组件模板)。

请提供您正在努力工作的基本代码,以这种方式帮助您会更容易。

这是一个使用模板的简单渲染流程的Widget系统的快速原型。我想你在你的应用程序中需要类似的东西。它没有被优化,它只是你的框架看起来的一个想法。

/** 
* Widget constructor 
*/ 
var Widget = function(config) { 
    // apply config 
    $.extend(this, config); 
    // attempt to render 
    this.render(); 
}; 

/** 
* Widget prototype 
*/ 
$.extend(Widget.prototype, { 
    // render target 
    renderTo: null, 
    // template 
    tpl: '<div class="container-panel">' + 
      '<p>${txt}</p>' + 
      '<div class="items-container"></div>' + 
     '</div>', 
    // template data 
    tplData: null, 
    // child items array 
    children: null, 
    // initial collapsed state 
    collapsed: false, 
    // widget's root element 
    el: null, 
    // default render target selector for child items 
    renderTarget: '.items-container', 

    render: function() { 
     var me = this, 
      renderDom 

     // render the widget 
     if(!this.rendered && this.renderTo && this.tpl) { 
      renderDom = $.tmpl(this.tpl, this.tplData); 
      // assume that first element is widget's root element 
      this.el = renderDom[0]; 
      $(this.renderTo).append(renderDom); 

      // clear the reference 
      renderDom = undefined; 

      // THIS IS JUST EXAMPLE CODE! Bind click handler... 
      $(this.el).find('p').first().click(function() { 
       me.collapsed ? me.expand() : me.collapse(); 
      });  

      // find render target for children 
      this.renderTarget = $(this.el).find(this.renderTarget).first(); 

      // render children if not collapsed 
      this.renderChildren(); 

      // set rendered flag 
      this.rendered = true; 
     } 
    }, 

    renderChildren: function() { 
     var children = this.children; 
     if(!this.collapsed && children && children.length) { 
      for(var i = 0, len = children.length; i < len; i++) { 
       // render children inside 
       children[i].renderTo = this.renderTarget; 
       children[i].render(); 
      } 
     } 
    }, 

    /** 
    * Expand template method. Override it. 
    */ 
    expand: function() { 
     this.collapsed = false; 
     this.renderChildren(); 
     this.renderTarget.show(); 
    }, 

    /** 
    * Collapse template method. Override it. 
    */  
    collapse: function() { 
     this.collapsed = true; 
     this.renderTarget.hide(); 
    } 
}); 

在这里,我预先定义的模板和硬编码上点击widget的第一款元素内发生的展开/折叠逻辑。

这是你将如何使用的部件:

// Using our widgets 
var containerPanel = new Widget({ 
    tplData: {txt: 'Hello world!'}, 
    renderTo: $('body'), 
    collapsed: true, 
    children: [ 
     new Widget({ 
      tplData: {txt: '&nbsp;&nbsp;Child 1'}, 
      collapsed: true, 
      children: [ 
       new Widget({ 
        tplData: {txt: '&nbsp;&nbsp;&nbsp;&nbsp;Child 1.1'} 
       }), 
       new Widget({ 
        tplData: {txt: '&nbsp;&nbsp;&nbsp;&nbsp;Child 1.2'} 
       }), 
       new Widget({ 
        tplData: {txt: '&nbsp;&nbsp;&nbsp;&nbsp;Child 1.3'} 
       }) 
      ] 
     }), 
     new Widget({ 
      tplData: {txt: '&nbsp;&nbsp;Child 2'} 
     }) 
    ] 
}); 

你可以看到的jsfiddle一个活生生的例子:http://jsfiddle.net/dipish/XDmWq/ 只需点击项目,并期待在动态生成的标记。

我认为代码是不言自明的,但随时可以提出任何问题。请注意,代码使用jQuery Templates Plugin,但这只是为了方便。

如果您的网络应用程序中有许多复杂的组件,您可能想要使用比裸露jQuery更严重的内容,例如ExtJSDojo Toolkit。除了很多其他的东西外,这样的框架通常为您提供了一个方便的类系统和基础构件/组件逻辑。

祝你好运!

+0

嘿德米特里感谢我正在开发基本代码的回应。 将发布ASAp。 :) – 2012-03-28 08:23:21

+0

德米特里多数民众赞成正是我需要.. 聚苯乙烯:有一点小故障,它每次增加孩子,但没有清除出口清单,但我可以处理,我想..谢谢...! :D:D:D – 2012-03-28 13:02:26

+0

不客气!通过'清除退出列表'你的意思是当你的面板崩溃时删除子html?如果是这样,将'this.renderTarget.empty();'添加到'collapse()'方法。但我不认为这是一个好主意,因为每当父面板展开时,重新渲染子项会导致性能开销。 – 2012-03-28 13:20:18

1

您需要对标记的外观更具体一些。但是,这里有一个粗略的例子:

//run this puppy when we need to append stuff 
var dynamicAppend = function(data, container) 
{ 
    var ul = container.children().slice(1,2); 
    var len = data.length; 
    for(var i = 0; i < len; i++) 
    { 
    var markup = [ 
    "<li class='" + data[i].thing + "'>", 
     "<span class='second_toggle' data-stuff='" + data[i].other_thing + "'></span>", 
     "<ul>", 
     "</ul>", 
    "</li>" 
    ]; 
    ul.append(markup.join()); 
    } 
} 

//do ajax stuff 
var handleAjax = function(data, container) 
{ 
    var json = { unique: data } 
    $.ajax({ 
    url: '', 
    data: json, 
    success: function(data) 
    { 
     if(data.success === 'your_flag' && data.newStuff) 
     { 
     dynamicAppend(data.newStuff, container); 
     } 
    } 
    }); 
} 

//first, you'll click the toggle 
var expand_toggle = $('.toggle'); 
expand_toggle.click(function(e){ 
    var that = $(this); 
    //grab some data that identifies the unique container you want to append to 
    var unique_id = that.data('some_identifier'); 
    var container = that.parents('.parent_container_class:first'); 
    handleAjax(unique_id, container); 
}); 

我会亲自把这个变成一个构造函数和做到这一点OOP的风格,但你可以得到的想法。

这里的一些标记:

<div class='parent_container_class'> 
    <span class='toggle' data-some_identifier='special_identifier_here'></span> 
    <ul></ul> 
</div>