Javascript.RU

Создать новую тему Ответ
 
Опции темы Искать в теме
  #1 (permalink)  
Старый 30.08.2013, 23:30
Новичок на форуме
Отправить личное сообщение для sergeyv Посмотреть профиль Найти все сообщения от sergeyv
 
Регистрация: 30.08.2013
Сообщений: 8

Загрузка контента в центральный фрейм по клику в tree.Panel
Здравствуйте,

Совсем недолго изучаю Javascript и в частности ExtJS и что-то у меня случился затык с тем, как загрузить контент в центральный фрейм по клику из меню tree.Panel.

Код TreeStore:
Ext.define('CM.store.MenuTreeStore', {
    extend: 'Ext.data.TreeStore',
    root: {
        expanded: true,
        children: [
            {
                // General section
                text: 'General',
                leaf: false,
                expanded: true,
                children: [
                    {
                        text: 'Partners',
                        leaf: true,
                        icon: 'images/group.png',
                        id: 'partnerslist'
                    },
                    {
                        text: 'Users',
                        leaf: true,
                        id: 'userslist'
                    }
                ]
            },
            {
                // Expenses
                text: 'Expenses',
                leaf: false,
                expanded: true,
                children: [
                    {
                        text: 'Serviss',
                        leaf: true,
                        id: 'servisslist'
                    }
                ]
            }
        ]
    }
});


Код навигации:
Ext.define('CM.view.Navigation', {
    extend: 'Ext.tree.Panel',
    alias: 'widget.appnavigation',
    width: 200,
    title: 'Menu',
    collapsible: true,
    collapseDirection: 'left',
    titleCollapse: true,
    store: 'MenuTreeStore',
    renderTo: Ext.getBody(),
    rootVisible: false,
    listeners:{
        itemclick: function(view,record) {
            if(record.isLeaf()) {
                console.log(record.data.id);
            } else if(record.isExpanded()) {
                record.collapse();
            } else {
                record.expand();
            }
        }
    }
});


Есть набор форм, примерно вот такого вида, которые предназначены для сбора разного рода данных, которые надо выводить в центральный фрейм border layout при клике в меню.
Ext.define('CM.view.user.List', {
    extend: 'Ext.grid.Panel',
    alias: 'widget.userlist',
    xtype: 'userslist',
    allowDeselect: true,
    columnLines: true,
    forceFit: true,
    title: 'All Users',
    store: 'Users',

    initComponent: function () {

        this.tbar = [{
            text: 'Add User', action: 'create', icon: '/images/add.png'
        }];
        this.columns = [
            { header: 'Name', dataIndex: 'name', flex: 1 },
            { header: 'Email', dataIndex: 'email', flex: 1 },
            { header: 'Phone', dataIndex: 'phone', flex: 1 }
        ];
        this.addEvents('removeitem');
        this.actions = {
            removeitem: Ext.create('Ext.Action', {
                text: 'Remove User',
                handler: function () { this.fireEvent('removeitem', this.getSelected()) },
                scope: this
            })
        };
        var contextMenu = Ext.create('Ext.menu.Menu', {
            items: [
                this.actions.removeitem
            ]
        });
        this.on({
            itemcontextmenu: function (view, rec, node, index, e) {
                e.stopEvent();
                contextMenu.showAt(e.getXY());
                return false;
            }
        });
        this.callParent(arguments);
    },
    getSelected: function () {
        var sm = this.getSelectionModel();
        var rs = sm.getSelection();
        if (rs.length) {
            return rs[0];
        }
        return null;
    }
});


По клику в меню, я добился того, что у меня в консоли отображается id leof-ов из MenuTreeStore, только что с ним дальше делать, пока не понимаю. Может кто из гуру подтолкнёт меня в нужном направлении? Желательно реальным примером.

Заранее спасибо!

P.S. в качестве серверной части у меня RoR 4.0

С уважением,
Сергей
Ответить с цитированием
  #2 (permalink)  
Старый 31.08.2013, 00:27
Профессор
Отправить личное сообщение для novikov Посмотреть профиль Найти все сообщения от novikov
 
Регистрация: 19.11.2012
Сообщений: 178

Сообщение от sergeyv Посмотреть сообщение
Совсем недолго изучаю Javascript и в частности ExtJS...
впечатляет...
Ответить с цитированием
  #3 (permalink)  
Старый 31.08.2013, 01:18
Профессор
Отправить личное сообщение для novikov Посмотреть профиль Найти все сообщения от novikov
 
Регистрация: 19.11.2012
Сообщений: 178

Предлагаю поместить все формы в контейнер с layout: 'fit'. Все формы скрыты при помощи параметра hidden: true. Когда пользователь щёлкает по меню, контроллер находит нуждую форму и загружает в неё данные. Снабдите формы параметром itemId, когда будете размещать их в контейнере, чтобы их можно было потом найти. Контейнеру тоже дайте какой-нибудь itemId.

Ext.define('CM.controller.NavigationController', {
     extend: 'Ext.app.Controller',
     init: function() {
          this.listen({
               component: {
                      appnavigation: {
                            itemclick: this.onNavigationItemClick
                      }
               }
          });
     },
     onNavigationItemClick: function(treeview, record) {
               var formContainer = Ext.ComponentQuery.query('[itemId="form-container"]')[0];
               // скрываем все формы
               Ext.Array.each(formContainer.items, function(formItem) {
                    formItem.hide();
               });
               // находим нужную форму
               var activeForm = Ext.ComponentQuery.query('[itemId="' + record.get('id') + '"]')[0];
               // показываем эту форму
               activeForm.show();
               // загружаем в активную форму данные (например, с сервера)
               if (activeForm.is('grid')) {
                       activeForm.getStore().load({
                              params: {

                              }
                       });
               }
     }
}


Хотя правильнее было бы иметь для каждой формы свой контроллер с обработчиком события, приходящего от контроллера навигации. Тогда не потребуется такое ветвление if (activeForm.is('grid')) {}.
Ответить с цитированием
  #4 (permalink)  
Старый 31.08.2013, 12:15
Новичок на форуме
Отправить личное сообщение для sergeyv Посмотреть профиль Найти все сообщения от sergeyv
 
Регистрация: 30.08.2013
Сообщений: 8

Здравствуйте, Александр.

Спасибо, буду пробовать, но вот сразу вопрос, если таких гридов у меня будет на 2-3, а 20, причём со всякими связанными гридами и прочими динамически вычесляемыми полями и функциями, то, я подозреваю, что такая реализация может очень сильно повлиять на перформанс и всё это хозяйство будет безбожно тормозить. Или я не прав?

Заранее спасибо за помощь.

С уважением,
Сергей
Ответить с цитированием
  #5 (permalink)  
Старый 31.08.2013, 15:08
Профессор
Отправить личное сообщение для novikov Посмотреть профиль Найти все сообщения от novikov
 
Регистрация: 19.11.2012
Сообщений: 178

Предполагяю, что на 20 формах тормозов не будет, если, конечно, не загружать таблицы из 50000 ячеек (и то только во время отрисовки).

Если вы считаете, что динамическая генерация компонентов ускорит работу приложения, можно запускать Ext.create('класс.Компонента') только при клике по соответствующему пункту меню и добавлять его в контейнер при помощи add() или renderTo.

У такого подхода есть свои недостатки. Я стремлюсь дистанцироваться от него как можно дальше. В том числе и из-за того, что отсутствующие компоненты не слышат события, на которые им следовало бы отреагировать.

Если вы опасаетесь, что поиск компонентов по строковым селекторам может стать причиной медленной работы приложения, то это вряд ли, поскольку в эту систему встроен механизм кэширования.

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

Если ожидаете, что с сервера нужно будет подгрузить слишком много данных для всевозможных форм и это вызовет задержку, то просто не грузите все данные с сервера сразу через autoLoad. Вместо этого подгружайте данные в обработчиках событий beforerender и т.п.

Вместо layout: 'fit', можно попробывать layout: 'card', но отложенная отрисовка компонентов может вызвать затруднения на перовом этапе, поэтому не советую.
Ответить с цитированием
  #6 (permalink)  
Старый 02.09.2013, 21:39
Новичок на форуме
Отправить личное сообщение для sergeyv Посмотреть профиль Найти все сообщения от sergeyv
 
Регистрация: 30.08.2013
Сообщений: 8

Александр, попробовал ваше решение, даже разобрался вроде как работать должно, но вот что-то не так пошло и в консоли я упираюсь в ошибку JS - Uncaught TypeError: Cannot call method 'hide' of undefined

При помощи console.log() вывел formContainer и вижу тут странный id: "contentPanel-1015". По вашему совету, добавил все формы в один контейнер и скрыл их. Может косяк какой-то из-за того, что я в качестве контейнера использую Panel?

Ext.define('CM.view.ContentPanel', {
    extend: 'Ext.panel.Panel',
    alias: 'widget.contentPanel',
    itemId: 'content',

    requires: [
        'CM.view.user.List',
        'CM.view.partner.List'
    ],

    title: '',
    layout: 'fit',

    initComponent: function() {
        var me = this;

        Ext.applyIf(me, {
            items: [
                {
                    xtype: 'partnerlist',
                    hidden: true,
                    itemId: 'partners'
                },
                {
                    xtype: 'userlist',
                    hidden: true,
                    itemId: 'users'
                }
            ]
        });

        me.callParent(arguments);
    }
});

и мой контроллер выглядит вот так:
Ext.define('CM.controller.Navigation', {
        extend: 'Ext.app.Controller',
        itemId: 'navigation',
        init: function() {
            this.listen({
                component: {
                    appnavigation: {
                        itemclick: this.onNavigationItemClick
                }
            }
        });
        },
        onNavigationItemClick: function(treeview, record) {
            var formContainer = Ext.ComponentQuery.query('[itemId="content"]')[0];
            // скрываем все формы
            console.log(formContainer);
            Ext.Array.each(formContainer.items, function(formItem) {
                formItem.hide();
            });
            // находим нужную форму
            var activeForm = Ext.ComponentQuery.query('[itemId="' + record.get('id') + '"]')[0];
            // показываем эту форму
            activeForm.show();
            // загружаем в активную форму данные (например, с сервера)
//            if (activeForm.is('grid')) {
//                activeForm.getStore().load({
//                        params: {
//                        }
//                });
//            }
        }
});


Может подскажете, что я не так понял и где путаюсь?

Заранее спасибо,
Сергей
Ответить с цитированием
  #7 (permalink)  
Старый 03.09.2013, 11:51
Профессор
Отправить личное сообщение для novikov Посмотреть профиль Найти все сообщения от novikov
 
Регистрация: 19.11.2012
Сообщений: 178

Сергей, id у formContainer, на мой взгляд, вполне нормальный. Он создался автоматически, поскольку он не был задан через параметр id.

Проблема в том, что я по ошибке неправильно указал способ перебора элементов контейнера. items не является массивом JavaScript, а экземпляром класса Ext.util.MixedCollection. Для перебора нужно использовать метод each().

http://docs.sencha.com/extjs/4.2.1/#...on-method-each

formContainer.items.each(function(formItem) {
    formItem.hide();
});
Ответить с цитированием
  #8 (permalink)  
Старый 03.09.2013, 12:27
Новичок на форуме
Отправить личное сообщение для sergeyv Посмотреть профиль Найти все сообщения от sergeyv
 
Регистрация: 30.08.2013
Сообщений: 8

Александр, Вы человек!

Спасибо огромное, всё заработало Пошёл штудировать матчасть

С уважением,
Сергей
Ответить с цитированием
  #9 (permalink)  
Старый 03.09.2013, 20:13
Новичок на форуме
Отправить личное сообщение для sergeyv Посмотреть профиль Найти все сообщения от sergeyv
 
Регистрация: 30.08.2013
Сообщений: 8

Здравствуйте,

опять затык

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

Методом проб и ошибок решил что ContentPanel стоит сделать Container'ом, а не Panel-ю
Ext.define('CM.view.ContentPanel', {
    extend: 'Ext.container.Container',
    //alias: 'widget.contentPanel',
    xtype: 'contentPanel',
    itemId: 'content',

    layout: 'fit',

    initComponent: function() {
        var me = this;

        Ext.applyIf(me, {
            items: [
                {
                    xtype: 'partnerlist',
                    hidden: true,
                    itemId: 'partners'
                },
                {
                    xtype: 'userlist',
                    hidden: true,
                    itemId: 'users'
                },
                {
                    xtype: 'partnercontactslist',
                    hidden: true,
                    itemId: 'partnercontactslist'
                }
            ]
        });

        me.callParent(arguments);
    }
});


и панель с гридами у меня вот такая:

Ext.define('CM.view.partnercontact.List', {
    extend: 'Ext.panel.Panel',
    xtype: 'partnercontactlist',
    forceFit: true,
    title: '',

    layout: {
        align: 'stretch',
        type: 'vbox'
    },

    initComponent: function() {
        var me = this;

        Ext.applyIf(me, {
            items: [
                {
                    xtype: 'partnerspanel'
                },
                {
                    xtype: 'partnercontacts'
                }
            ]
        });

        me.callParent(arguments);
    }
});


Ну и соответственно гриды. Главный:
Ext.define('CM.view.partnercontact.Partners', {
    extend: 'Ext.grid.Panel',
    xtype: 'partnerspanel',

    title: 'Partners',
    store: 'Partners',

    initComponent: function() {
        var me = this;

        Ext.applyIf(me, {
            columns: [
                {
                    xtype: 'gridcolumn',
                    header: 'Name',
                    dataIndex: 'name',
                    flex: 1
                },
                {
                    xtype: 'gridcolumn',
                    header: 'Phone',
                    dataIndex: 'phone',
                    flex: 1
                },
                {
                    xtype: 'gridcolumn',
                    header: 'Fax',
                    dataIndex: 'fax',
                    flex: 1
                },
                {
                    xtype: 'gridcolumn',
                    header: 'Address',
                    dataIndex: 'address',
                    flex: 1
                }
            ]
        });

        me.callParent(arguments);
    }

});


и связанный
Ext.define('CM.view.partnercontact.Contacts', {
    extend: 'Ext.grid.Panel',
    xtype: 'partnercontacts',

    title: 'Related contacts',
    store: 'Contacts',

    initComponent: function() {
        var me = this;

        Ext.applyIf(me, {
            columns: [
                {
                    xtype: 'gridcolumn',
                    header: 'Name',
                    dataIndex: 'name',
                    flex: 1
                },
                {
                    xtype: 'gridcolumn',
                    header: 'Phone',
                    dataIndex: 'phone',
                    flex: 1
                },
                {
                    xtype: 'gridcolumn',
                    header: 'Email',
                    dataIndex: 'email',
                    flex: 1
                },
                {
                    xtype: 'numbercolumn',
                    header: 'Partner ID',
                    dataIndex: 'partner_id',
                    flex: 0
                }
            ]
        });

        me.callParent(arguments);
    }

});


в MenuTreeStore вот такое добавил:

{
                        text: 'Partners/Contacts',
                        leaf: true,
                        icon: 'images/group_link.png',
                        id: 'partnercontactslist'
                    }


Но почему-то вообще всё ломается. Загружается только дерево навигации, ну и вообщем всё летит в тар тарары.

Комментирую в ContentPanel новую форму, всё возвращается на места и работает.

//                {
//                    xtype: 'partnercontactslist',
//                    hidden: true,
//                    itemId: 'partnercontactslist'
//                }


Отдельный котнроллер я под эту форму не создавал, потому как вообщем-то и так должно работать, вроде

Пните пожалуйста в нужном направлении.

Заранее спасибо за помощь.

С уважением,
Сергей
Ответить с цитированием
  #10 (permalink)  
Старый 06.09.2013, 20:40
Новичок на форуме
Отправить личное сообщение для sergeyv Посмотреть профиль Найти все сообщения от sergeyv
 
Регистрация: 30.08.2013
Сообщений: 8

Проблема решилась.

Создал panel с
layout: {
        align: 'stretch',
        type: 'vbox'
    },
    title: '',


И всё там аккуратненько уложил. Завелось и зажило. Спасибо!
Ответить с цитированием
Ответ



Опции темы Искать в теме
Искать в теме:

Расширенный поиск


Похожие темы
Тема Автор Раздел Ответов Последнее сообщение
Загрузка контента в модальном окне Nitro_Generate Общие вопросы Javascript 2 08.12.2012 17:30
загрузка картинки во фрейм) shikuwa Общие вопросы Javascript 2 19.11.2012 10:01
Загрузка изображения из фрейма во фрейм Hardip Events/DOM/Window 0 10.03.2012 13:23
JS загрузка контента MCTrane Общие вопросы Javascript 11 27.09.2011 00:35
Загрузка контента без перезагрузки страницы vah-smile AJAX и COMET 3 30.03.2011 16:37