Вложенные шаблоны в JavaScript / jQuery / AJAX - PullRequest
1 голос
/ 28 марта 2012

Я пытаюсь выполнить модуль, в котором мне нужно использовать вложенные шаблоны, и я застрял в том, КАК я могу это сделать.

в основном в моем интерфейсе есть 3 уровня, например, скажем, уровень 1, уровень 2, уровень 3. Поэтому, когда страница отображается, мне нужно визуализировать только уровень 1. Но когда пользователь нажимает кнопку «развернуть» любого элемента уровня 1, мне нужно отобразить соответствующие элементы уровня 2 (не все) ниже выбранного элемента уровня 1.

Теперь, когда пользователь нажимает «развернуть» любого элемента уровня 2, соответствующий уровень 3 должен отображаться ..

Подводя итог, он должен быть похож на левую панель навигации Windows Explorer.!

Ответы [ 2 ]

1 голос
/ 28 марта 2012

Вы должны быть более точными в том, как будет выглядеть разметка. Однако вот пример:

//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 );
});

Я бы лично поместил это в конструктор и сделал бы это в стиле ООП, но вы можете понять это.

Вот некоторая разметка:

<div class='parent_container_class'>
  <span class='toggle' data-some_identifier='special_identifier_here'></span>
  <ul></ul>
</div>
1 голос
/ 28 марта 2012

Как правило, вы должны определить отдельные компоненты для каждого уровня, назначить шаблон для каждого из ваших компонентов и реализовать что-то вроде 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();
    }
});

Здесь я предварительно определил шаблоны и жестко запрограммировал логику расширения / свертывания, которая происходит при щелчке внутри первого элемента абзаца виджета.

Вот как бы вы использовали виджеты:

// 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 , но это только для удобства.

Если в вашем веб-приложении много сложных компонентов, вы можете использовать что-то более серьезное, чем простой jQuery, например ExtJS или Dojo Toolkit . Такие структуры обычно предоставляют вам удобную систему классов и базовую логику виджетов / компонентов для построения, помимо множества других вещей.

Удачи!

...