Как стать автором
Обновить

Руководство по мелочам в Ext JS

Время на прочтение5 мин
Количество просмотров39K
Добрый день, хабрапользователи! Сегодня я бы хотел поделиться с проблемами, которые обычно отталкивают добропорядочных программистов от использования фреймворка — Ext JS. Опишу конкретную ситуацию: в один прекрасный день после некоторого времени потраченного на просмотр возможностей, которые предлагает Ext JS, возникает непреодолимое желание попробовать его «в деле». Качается дистрибутив, ставится на локальный сервер и запускаются красивые примеры гридов, форм и, даже, готового рабочего стола! Разработчик меняет пару «фишечек», все вроде легко и просто. Резонно в голове бой-скаута возникает идея сделать некий коммерческий проект на Ext JS (чаще всего это бывают различного рода CMS, админки, CRM). И тут начинается самое интересное…

После недели работы с Ext JS голова бой-скаута начинает полуавтоматически генерировать мысли о его собственной ничтожности и невообразимой сложности Ext JS. И, обиженный на Ext JS, разработчик развевает по ветру пепел желания работы на этом фреймворке. А жаль…

Поэтому в этой статье я хочу описать проблемы, с которыми я столкнулся при разработке системы управления контентом и решения этих проблем. Все примеры проверены на Ext JS версии 3.4.

1. Автоматическая подгонка размеров содержимого окна.
Задача: встроить в Ext.Window форму (Ext.form.FormPanel). Первое, что приходит в голову:

Ext.onReady(function(){

   var win = new Ext.Window({
		title: "title",
		border: false,
		width: 400,
		height: 400,
		items: [{
			width: 390,
			height: 380,
			items: [new Ext.form.FormPanel({
				 frame: true,
				 items: {xtype: 'textfield'}
			})]
		}]
   });

 win.show();
});

В данном случае разработчику требуется «подогнать» размеры формы под размеры окна. Если подогнано неверно — снизу появляется раздражающая белая полоска:

image

Для этой ситуации разработчики Ext JS предусмотрели параметр layout в конфигурации Ext.Window. Конкретно для этого случая используется layout: 'fit':

Ext.onReady(function(){

   var win = new Ext.Window({
		title: "title",
		border: false,
		width: 400,
		height: 400,
		layout:'fit',
		items: [
			new Ext.form.FormPanel({
				frame: true,
				items: {xtype: 'textfield'}
			})
		]
 });

 win.show();
});

image

2. Разделение полей формы на 2 и более колонок (или размещение нескольких полей формы на одной строке).
Если просто прописать в items формы несколько полей формы, то они выстроятся ровно друг под дружкой, примерно вот так:

Ext.onReady(function(){

   var win = new Ext.Window({
	title: "title",
	border: false,
	width: 400,
	height: 200,
	layout:'fit',
	items: [
		new Ext.form.FormPanel({
			frame: true,
			items: [{
				xtype: 'textfield',
				fieldLabel: 'field1'
			},{
				xtype: 'textfield',
				fieldLabel: 'field2'
			},{
				xtype: 'textfield',
				fieldLabel: 'field3'
			},{
				xtype: 'textfield',
				fieldLabel: 'field4'
			}]
		})
	]
 });

 win.show();
 
});

image

Нам же требуется, чтобы было примерно так:

image

Делается это так:
(Внимание! Для понимания следующего куска кода требуется немного логического мышления)
Ext.onReady(function(){

   var win = new Ext.Window({
		title: "title",
		border: false,
		width: 400,
		height: 200,
		layout:'fit',
		items: [
			new Ext.form.FormPanel({
				frame: true,
				// Нас интересует код от этого места
				layout: 'column',
				defaults: {
					xtype: 'form',
					columnWidth:0.5,
					labelAlign: 'top',
					anchor: '100%'
				},
				// до этого
				// 1
				items: [{
					// 2, столбец 1
					items:[{
							xtype: 'textfield',
							fieldLabel: 'field1'
						},{
							xtype: 'textfield',
							fieldLabel: 'field2'
						}]
				},{
					// 3, столбец 2
					items:[{
							xtype: 'textfield',
							fieldLabel: 'field3'
						},{
							xtype: 'textfield',
							fieldLabel: 'field4'
						}]
				}]
			})
		]
 });

 win.show();
 
});


Итак. Приступим к разбору кода. Первое, что нужно для разделения формы на колонки параметр layout: 'column', который сообщает форме, что форму следует разделить на колонки. Далее вступает в дело параметр defaults, который сообщает настройки по умолчанию для нижестоящего items. Эти настройки передаются каждому объекту в этом массиве (объектам items 2, items 3).

Почему в defaults так много параметров и зачем они нужны, для простого разбиения формы на колонки? Отвечаю:
xtype: 'form' — без этого параметра, не отображались бы fieldLabel для каждого поля,
columnWidth — определяет ширину стобцов по умолчанию (в объектах 2 и 3 можно ширину столбца переопределять),
labelAlign — определяет положение fieldLabel (top — сверху),
anchor — ширина в процентах объектов 2 и 3.

Так же обратите внимание на то, что в отличие от предыдущего примера, в items объекта 1 добавляется еще один уровень вложенности.

3. Управление рендерингом записей в гриде.
Часто случается так, что хочется как-то изменить содержимое ячейки грида, в зависимости от будущего значения этого содержимого. На помощь приходит параметр грида — renderer.

Допустим у нас на старте есть грид:

image

Исходный код:

var data = {
   totalCount : 3,
   banners: [{"is_active": 0,"ID": 1},{"is_active": 0,"ID" : 3},{"is_active": 1,"ID": 4}]
}

var view = new Ext.Viewport({
	layout: 'fit',
	items: [{
		xtype: 'grid',
		columns: [
			{header: "ID", align : 'left', width: 30, sortable: true, dataIndex: 'ID'},
			{
				header: "Активность", align : 'left', width: 100, sortable: true,
				dataIndex: 'is_active'
			}
		],
		store: new Ext.data.GroupingStore({
			data: data,
			fields: [{name: 'ID'},{name: 'is_active'}],
			reader: new Ext.data.JsonReader({
					root: 'banners',
					totalProperty: 'totalCount',
					id: 'ID'
				},
				Ext.data.Record.create([
					{name: 'ID'},
					{name: 'is_active'}
				])
			)
		}),
		view: new Ext.grid.GridView({
			forceFit: false,
		}),
		listeners: {}
	}]

});

view.render(Ext.getBody());
});


Можно сделать так:
image

Исходный код:

var renderActivity = function(val) {
	if(val == 1) 
		return "<span style='color: green'>"+val+"</span>";
	else
		return "<span style='color: red'>"+val+"</span>";
}

var data = {
   totalCount : 3,
   banners: [{"is_active": 0,"ID": 1},{"is_active": 0,"ID": 3},{"is_active": 1,"ID": 4}]
}

var view = new Ext.Viewport({
	layout: 'fit',
	items: [{
		xtype: 'grid',
		columns: [
			{header: "ID", align : 'left', width: 30, sortable: true, dataIndex: 'ID'},
			{
				header: "Активность", align : 'left', width: 100, sortable: true,
				dataIndex: 'is_active', renderer: renderActivity
			}
		],
		store: new Ext.data.GroupingStore({
			data: data,
			fields: [{name: 'ID'},{name: 'is_active'}],
			reader: new Ext.data.JsonReader({
					root: 'banners',
					totalProperty: 'totalCount',
					id: 'ID'
					}, Ext.data.Record.create([
						{name: 'ID'},
						{name: 'is_active'}
					])
			)
		}),
		view: new Ext.grid.GridView({
			forceFit: false,
		}),
		listeners: {}
	}]

});

view.render(Ext.getBody());
});


Как видно, вначале была добавлена функция renderActivity, которая разукрашивает содержимое ячейки в зависимости от значения в зеленый или красный цвет. Далее эта функция вызывается в описании настроек колонки «Активность» — renderer: renderActivity. Таким образом содержимое ячеек грида можно легко и просто изменять под любые, даже, порой, не совсем пристойные, нужды.

Если посвятить изучению Ext JS побольше времени, то действительно поражаешься, какие гибкие возможности предоставляет этот фреймворк. Многие говорят, что сайты на Ext JS сложно кастомизировать. Не верьте этому. Лично я считаю, что у фреймворка просто достаточно высокий порог вхождения.

Разрабатывая на Ext JS уже около года, я «съел не одну собаку». Таких мелочей у меня накопилось великое множество. Поэтому, если хабрасообщество пожелает и в дальнейшем читать мои статьи по Ext JS, я с радостью их буду писать.

На этом извольте закончить мою первую статью, надеюсь она вам понравилась.
Теги:
Хабы:
Всего голосов 47: ↑45 и ↓2+43
Комментарии73

Публикации

Истории

Ближайшие события

19 августа – 20 октября
RuCode.Финал. Чемпионат по алгоритмическому программированию и ИИ
МоскваНижний НовгородЕкатеринбургСтавропольНовосибрискКалининградПермьВладивостокЧитаКраснорскТомскИжевскПетрозаводскКазаньКурскТюменьВолгоградУфаМурманскБишкекСочиУльяновскСаратовИркутскДолгопрудныйОнлайн
3 – 18 октября
Kokoc Hackathon 2024
Онлайн
24 – 25 октября
One Day Offer для AQA Engineer и Developers
Онлайн
25 октября
Конференция по росту продуктов EGC’24
МоскваОнлайн
26 октября
ProIT Network Fest
Санкт-Петербург
7 – 8 ноября
Конференция byteoilgas_conf 2024
МоскваОнлайн
7 – 8 ноября
Конференция «Матемаркетинг»
МоскваОнлайн
15 – 16 ноября
IT-конференция Merge Skolkovo
Москва
25 – 26 апреля
IT-конференция Merge Tatarstan 2025
Казань