.. / Шаг 5. Детализация - просмотрщик записей таблицы в отдельных вкладках

  1. ExtJS-large-application

На этом шаге особо важного ничего нет. Здесь я просто создаю новый компонент на базе CommonGrid - таблицы для просмотра записей и CommonTab. Поскольку в таблицу все данные не уместить, да и не надо, нужно иметь какой-то просмотрщик записи. Мне кажется что такие вещи лучше делать в отдельном окне, но заказчик настоял на том, чтобы детали записи отображались в закладках. Так я и сделал.

В CommonTab, вообще говоря грузить можно что угодно. Туда в качестве данных передается класс, который нужно подгрузить. Что-там прячется в этом классе самом компоненту CommonTab неизвестно, и в принципе туда можно например загрузить редактор или вообще сколь угодно сложный компонент с несколькими редакторами, табличками, закладками и прочими навесками, но здесь я ограничусь именно просмотрщиками - двух типов - с Ajax-подгрузкой готовой страницы и с json-данными, которые при получении с сервера будут преобразованы через ExtJS - шаблонизатор, который мне очень не нравится, как не нравится любой шаблонизатор отличный от XSLT

Итак для начала я создам новый класс c длинным названием CommonGridTabView:

 Ext.define("App.Common.CommonGridTabView",{
      extend: 'Ext.Panel',
      alias             : "widget.commongridtabview",
      layout: 'border',
      initComponent: function() {
                    // создаю табличку на базе CommonGrid
                    this.grid=Ext.create('App.Common.CommonGrid', {
                          region: 'north',
                          height:300,
                          itemId:this.itemId,
                          split:true,
                          family:this.family,
                          data:this.data,
                          conf:this.conf
                    });
                    // создаю набор закладок на базе CommonTab
                    this.tabs=Ext.create('App.Common.CommonTab', {
                                            region: 'center',
                                            autoScroll:true,
                                            family:this.family,
                                            bodyStyle: "background: #ffffff;padding:0px;"
                                        });

                    // объединяю оба компонента на одной панели
                    this.items = [this.grid,this.tabs];
                    // Подписка на событие открытия вкладки с просмотром через общий обозреватель приложения
                    // само событие происходит в  CommonGrid
                    app.Event.subscribe('view',this);
                    App.Common.CommonGridTabView.superclass.initComponent.apply(this, arguments);
                },
       listeners: {
         Ev_view: function(obj,data){
             // через CommonTab создаю новую вкладку
             // и передаю туда класс вьюера для создания 
             if (data.itemId != this.itemId) return;
             this.tabs.openTab({
                    family:this.family,
                    app:this.family+'View',
                    data:data,
                    url:this.data.url,
                    id: data.rec.id,
                    title:data.rec.id
                  });

         }

       }
    });

Комментировать здесь особо нечего - здесь все берется из предыдущих шагов - два уже известных компонента связаны между собой и через глобальный обозреватель запускается создание новой вкладки с просмотрщиком детализации записи. Теперь нарисую другой класс, который будет заниматься визуализацией App.Common.CommonViewHtml. Здесь как я уже раньше написал я считаю самым лучшим детализацию делать на стороне сервера. Класс для этого будет основным и я его опишу:

Ext.define("App.Common.CommonViewHtml",{
      extend: 'Ext.Panel',
      alias             : "widget.commonviewhtml",
      title : 'FirstView',
      initComponent: function() {
                    this.html = "<div id='c"+this.id+"'></div>";
                    App.Common.CommonViewHtml.superclass.initComponent.apply(this, arguments);
                    // Подписка на событие изменение содержимого  через общий обозреватель приложения
                    app.Event.subscribe('changed',this);
                  },
      listeners:{
          // перерисовка измененной записи
          Ev_changed: function(obj,data) {
               if (this.itemId == data.id) this.load();
            },
            // вызываю загрузку после рендеринга
            afterrender:function(){
              this.load();
            }
      },
      load:function(){
         var container = Ext.get('c'+this.id);
          this.removeAll(); /* очистка контейнера */
            Ext.Ajax.request({
                    url: this.data.url+'&view='+this.data.id,
                    success: function(response){
                       container.update(response.responseText);
                    }
                });
      }
    });


Фактически это обычная панель, содержимое которой обновляется через Ajax. Как сделать обновление по-человечьи, я не нашел. Поэтому пока сделаю через жопу DOM. Я знаю, это плохо, потом исправлю. Ну и естественно код кастомного контрола App.SecondView для данных типа Second

Ext.define("App.SecondView",{extend: 'App.Common.CommonViewHtml'}); 

От такого класса сразу поплохело. Потому что по предложенной схеме образования дочерних классов придется плодить очень много одинаковых и пустых классов -просмотрщиков. От этого я буду избавляться позже. А пока для любителей клиентских шаблонизаторов я без всяких комментариев приведу код для класса просмотрщика с шаблонизацией на клиенте:

Ext.define("App.Common.CommonViewTpl",{
      extend: 'Ext.Panel',
      alias             : "widget.commonviewtpl",
      title : 'FirstView',
      initComponent: function() {
                    App.Common.CommonViewTpl.superclass.initComponent.apply(this, arguments);
                    this.conf = this.conf || {view:{}};
                    this.conf.view = this.conf.view || {tpl:null};
                    app.Event.subscribe('changed',this);  // Подписка на событие удаления записи через общий обозреватель приложения
                  },
      defaultTpl:function(rec){
            var v,i,tpl='';
            for(i in rec)  if (rec[i].length > 0)
                {
                 v='{'+i+'}';
                 if (i == 'mail') v='<a target="_blank" href="mailto:{'+i+'}">{'+i+'}</a>'; else
                 if (i == 'url') v='<a target="_blank" href="http://{'+i+'}">{'+i+'}</a>';
                 tpl += "<tr><th><b>"+i+"</b></th><td>"+v+"</td></tr>";
                }
            tpl='<table class="commonTable">'+tpl+'</table>';
            return tpl;
      },
      listeners:{
          Ev_changed: function(obj,data) {  // перерисовка измененной записи
               if (this.itemId == data.id) this.load();
            },
          afterrender:function(){
          this.load();
        }
      },
      load:function(){
            data=this.data;
            /* this.removeAll();   очистка контейнера нихуя не работает */
            /* this.body.clean();  очистка контейнера нихуя не работает */
            this.body.dom.innerHTML=''; /* а вот так работает :( */
            var that = this;
            var _tpl = this.conf.view.tpl || this.defaultTpl;
            Ext.Ajax.request({
                    url: data.url+'&one='+data.id,
                    success: function(response){
                        var rec=Ext.JSON.decode(response.responseText);
                        rec=rec.data;
                        var tpl=_tpl;
                        if (typeof(tpl) == 'function') {
                            tpl = _tpl(rec);
                        }
                        Ext.create('Ext.Template',tpl)
                        .compile()
                        .append(that.body, rec);

                    }
                });

      }
    });

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

И кроме того можно указать какой-то отдельный шаблон для парсинга, Его пример можно посмотреть в App.ThirdView в архиве, где собраны все исходники. Архи влежит все там же my_big_application_ExtJS4.zip в директорию step5

  1. 2012-03-26
  2. ExtJS-large-application
  1. php-zametki.ru/javascript-laboratoriya/79-svoi-sobytiya-javascript-observer.html - Свои события или observer на Javascript
Go Index Test