0

I need to create Twitter Bootstrap basic NavBar component in my ExtJS 4.2 application. All I want to make my component generate the following html:

<div class="navbar navbar-inverse navbar-fixed-top">
  <div class="navbar-inner">
    <ul class="nav">
      <li class="active"><a href="#"><i class="icon1"></i> Item #1</a></li>
      <li><a href="#"><i class="icon2"></i> Item #3</a></li>
      <li><a href="#"><i class="icon3"></i> Item #3</a></li>
    </ul>
  </div>
</div>

I've created two views (NavBar and NavBarItem correspondingly):

Ext.define('My.view.layout.Navbar', {
   extend: 'Ext.container.Container',
   xtype: 'navbar',
   cls: 'navbar navbar-inverse navbar-fixed-top',
   defaultType: 'navbaritem',
   initComponent: function() {
       Ext.apply(this, {
           items: [
               {
                   title: 'Item #1',
                   icon: 'icon1',
                   selected: true
               },
               {
                   title: 'Item #2',
                   icon: 'icon2'
               },
               {
                   title: 'Item #3',
                   icon: 'icon3'
               }
           ]
       });
       this.callParent(arguments);
   }
});

Ext.define('My.view.layout.NavbarItem', {
    extend: 'Ext.Component',
    xtype: 'navbaritem',
    autoEl: { tag: 'li' },
    config: {
        title: '',
        icon: null,
        selected: false
    },
    renderTpl: '<a href="#">{icon}{title}</a>',
    initComponent: function() {
        ....
        this.callParent(arguments);
    }
});

I get something like this as an output:

<div class="navbar navbar-inverse navbar-fixed-top">
   <li class="active"><a href="#"><i class="icon1"></i> Item #1</a></li>
   <li><a href="#"><i class="icon2"></i> Item #3</a></li>
   <li><a href="#"><i class="icon3"></i> Item #3</a></li>
</div>

How can I modify my NavBar view in order it could have a custom template and children components could be added to a particular element?

Stas
  • 23
  • 2
  • 6
  • You could use an `Ext.view.View` and create your own custom `XTemplate` that mimics your required div structure. There are some examples in the Ext docs that do a good job demoing both the View and XTemplates. – Chris Farmer Aug 14 '13 at 18:47

1 Answers1

0

You're halfway there: your child items are rendering more or less properly, but the container will require a bit of work to avoid rendering extra elements. The catch here is that for a container, the rendering process is tightly intertwined with the layout and in fact containers render from within a layout. So you will need to fudge the auto layout a bit:

Ext.define('My.view.layout.NavBar', {
    extend: 'Ext.container.Container',
    alias:  'widget.navbar',  // Not xtype here!

    defaultType: 'navbaritem',

    // Let's be declarative
    items: [{
        title: 'Item #1',
        icon: 'icon1',
        selected: true
    }, {
        title: 'Item #2',
        icon: 'icon2'
    }, {
        title: 'Item #3',
        icon: 'icon3'
    }],

    renderTpl: [
        '<div class="navbar-inner">',
            '<ul class="nav">',
                '{%this.renderChildren(out,values)%}',
            '</ul>',
        '</div>',

        {
            renderChildren: function(out, renderData) {
                // We have to be careful here, as `this`
                // points to the renderTpl reference!
                var me = renderData.$comp.layout,
                    tree = me.getRenderTree();

                if (tree) {
                    Ext.DomHelper.generateMarkup(tree, out);
                }
            }
        }
    ]
});

Instantiating this container will give you approximately this output:

<div ...>
    <div class="navbar-inner">
        <ul class="nav" ...>
            <li ...>
                <a href="#">...</a>
            </li>
            <li ...>
                <a href="#">...</a>
            </li>
            <li ...>
                <a href="#">...</a>
            </li>
        </ul>
    </div>
</div>

I'm simplifying here and the actual elements rendered to the DOM will get a lot of auto-generated classes, ids, and other attributes, so you will have to tweak your templates even more, but I hope you get the gist of it.

Alex Tokarev
  • 4,821
  • 1
  • 20
  • 30
  • Thank you, it works for me. But I didn't find anything about this approach in ExtJS documentation. – Stas Aug 22 '13 at 16:37
  • @Stas Well, these things are probably a bit too deep for the regular documentation and will do more harm than good. Ext JS layouts are incredibly flexible and powerful, but the price we have to pay is that they're fiendishly complex, too. You have to know perfectly well what you're doing if you want to muck with the layouts, and if you do you probably won't need the docs anyway. :) – Alex Tokarev Aug 22 '13 at 19:11