ExtJS начиная с версии 5 для связки полей в виде и модели использует механизм Binding.
В данном учебном материале приведен пример CRUD на базе формы и таблицы.
В программе используются следующие классы:
MyApp.model.Person (Класс записи в модели сущности персоны)
MyApp.store.Personnel (Класс хранилища записей в модели с начальными данными)
MyApp.view.main.MainModel (Класс модели вида с механизмом Binding)
MyApp.view.main.Form (Класс формы, где поля формы связаны с моделью механизмом Binding)
MyApp.view.main.List (Класс таблицы, где поля записей в таблице связаны с моделью механизмом Binding)
MyApp.view.main.MainController (Класс контроллера, определяющий привязанные обработчики действий к виду)
MyApp.view.main.Main (Класс панели вида с размещенным на ней формой и таблицей)
MyApp.Application (Класс приложения)
Исходный код:
MyApp.model.Person:
Ext.define('MyApp.model.Person', {
extend: 'Ext.data.Model',
alias: 'model.person',
fields: [
'id', 'name', 'title', 'description', 'date'
]
});
MyApp.store.Personnel:
Ext.define('MyApp.store.Personnel', {
extend: 'Ext.data.Store',
alias: 'store.personnel',
requires: [
'MyApp.model.Person'
],
fields: [
'id', 'name', 'title', 'description', 'date'
],
data: {
items: [{
id: 1,
name: 'Jean Luc1',
title: 'File1',
description: 'Content1',
date: '01/01/2015'
}, {
id: 2,
name: 'Jean Luc2',
title: 'File2',
description: 'Content2',
date: '02/01/2015'
}, {
id: 3,
name: 'Jean Luc3',
title: 'File3',
description: 'Content3',
date: '03/01/2015'
}, {
id: 4,
name: 'Jean Luc4',
title: 'File4',
description: 'Content4',
date: '04/01/2015'
}]
},
proxy: {
type: 'memory',
reader: {
type: 'json',
rootProperty: 'items'
}
}
});
MyApp.view.main.MainModel:
Ext.define('MyApp.view.main.MainModel', {
extend: 'Ext.app.ViewModel',
alias: 'viewmodel.main',
stores: {
persons: {
type: 'personnel',
autoLoad: true
}
},
formulas: {
person: {
bind: {
bindTo: '{personGrid.selection}',
deep: true
},
get: function (record) {
return record;
},
set: function (record) {
if (!record.isModel) {
record = this.get('persons').getById(record.id);
this.set('person', record);
}
}
}
}
});
В данном классе обьявлена связь хранилища сущностей персон с полем в модели:
stores: {
persons: {
type: 'personnel',
autoLoad: true
}
},
Также приведен механиз Binding для связи выделенной строки таблицы с вычесляемым полем person модели:
formulas: {
person: {
bind: {
bindTo: '{personGrid.selection}',
deep: true
},
MyApp.view.main.Form:
Ext.define('MyApp.view.main.Form', {
extend: 'Ext.form.Panel',
xtype: 'mainform',
viewModel: 'main',
requires: [
'MyApp.view.main.MainModel'
],
title: 'Edit form',
modelValidation: true,
layout: 'anchor',
defaults: {
labelWidth: 100,
selectOnFocus: true,
anchor: '95%',
allowBlank: false,
style: 'margin: 30px 0px 0px 30px;'
},
items: [{
xtype: 'numberfield',
name: 'id',
fieldLabel: 'ID',
bind: '{person.id}'
}, {
xtype: 'textfield',
name: 'name',
fieldLabel: 'Name',
bind: '{person.name}'
}, {
xtype: 'textfield',
name: 'title',
fieldLabel: 'Title',
anchor: '95%',
bind: '{person.title}'
}, {
xtype: 'textareafield',
name: 'description',
fieldLabel: 'Decription',
anchor: '95%',
bind: '{person.description}'
}, {
xtype: 'datefield',
name: 'date',
fieldLabel: 'Date',
maxValue: new Date(),
bind: '{person.date}'
}, {
xtype: 'panel',
border: false,
anchor: '100%',
height: 100,
style: '',
layout: {
type: 'hbox',
align: 'middle',
pack: 'center'
},
items: [{
xtype: 'button',
minWidth: 70,
text: 'Save',
listeners: {
click: 'saveItem'
}
}]
}]
});
В полях таблицы задействован механиз Binding их связи с вычесляемым полем модели person
items: [{
xtype: 'numberfield',
name: 'id',
fieldLabel: 'ID',
bind: '{person.id}'
},...
В данном поле происходит связь значения value поля со значением person.id вычесляемого поля модели person и его ключом id.
На панели формы добавлена кнопка предназначенная для сохранения значений формы в изменяемую строку таблицы
{
xtype: 'button',
minWidth: 70,
text: 'Save',
listeners: {
click: 'saveItem'
}
}
Обработчик клика по кнопке будет объявлен в контроллере.
MyApp.view.main.List:
Ext.define('MyApp.view.main.List', {
extend: 'Ext.grid.Panel',
xtype: 'mainlist',
requires: [
'Ext.grid.plugin.CellEditing',
'MyApp.view.main.MainModel',
'MyApp.store.Personnel'
],
plugins: [{
ptype: 'cellediting'
}],
modelValidation: true,
title: 'Personnel',
publishes: ['person'],
bind: {
store: '{persons}'
},
reference: 'personGrid',
columns: [{
text: 'ID',
dataIndex: 'id',
editor: {
bind: '{person.id}',
selectOnFocus: true
}
}, {
text: 'Name',
dataIndex: 'name',
editor: {
bind: '{person.name}',
selectOnFocus: true
}
}, {
text: 'Title',
dataIndex: 'title',
editor: {
bind: '{person.title}',
selectOnFocus: true
}
}, {
text: 'Description',
dataIndex: 'description',
flex: 1,
editor: {
bind: '{person.description}',
selectOnFocus: true
}
}, {
text: 'Date',
dataIndex: 'date',
xtype: 'datecolumn',
flex: 1,
editor: {
bind: '{person.date}',
selectOnFocus: true
}
}],
listeners: {
select: 'loadToForm'
},
tbar: [{
xtype: 'button',
text: 'Refresh',
listeners: {
click: 'refreshGrid'
}
}, '->', {
xtype: 'button',
text: 'Add empty',
listeners: {
click: 'addItem'
}
}, {
xtype: 'button',
text: 'Edit',
listeners: {
click: 'editItem'
}
}, {
xtype: 'button',
text: 'Delete selected',
listeners: {
click: 'deleteItem'
}
}]
});
В данном классе установлен механиз Binding для хранилища записей таблицы:
bind: {
store: '{persons}'
},
Объявление имени таблицы для использования механизма Binding в модели
reference: 'personGrid'
Подключен механизм Binding для значений столбцов в изменяемой строке таблицы:
columns: [{
text: 'ID',
dataIndex: 'id',
editor: {
bind: '{person.id}',
selectOnFocus: true
}
}, ...
В данном случае значение столбца id изменяемой строки связано механизмом Binding с вычесляемым полем person модели и его ключом id.
В tbar таблицы добавлены кнопки добавления пустой записи таблицы (обработчик клика addItem находится в контроллере), редактирование записи таблицы в форме (editItem), удаления записи из таблицы (deleteItem).
MyApp.view.main.MainController:
Ext.define('MyApp.view.main.MainController', {
extend: 'Ext.app.ViewController',
alias: 'controller.main',
loadToForm: function (item, record) {
},
refreshGrid: function (button) {
this.doFormButton(button, 'cancel');
},
saveItem: function (button) {
this.doFormButton(button, 'save');
},
addItem: function (button) {
var vm = this.getViewModel();
var store = vm.getStore('persons');
store.sort({
property: 'id',
direction: 'ASC'
});
var lastRecord = store.last();
var record = store.insert(0, {
id: lastRecord.data.id + 1
})[0];
vm.set('person', record);
store.commitChanges();
},
editItem: function (button) {
var mainPanel = button.up('app-main');
var grid = mainPanel.down('grid');
var records = grid.getSelectionModel().getSelection();
var record = records[0];
var form = mainPanel.down('form');
var formvm = form.getViewModel();
form.getForm().setValues(record.data);
},
deleteItem: function (button) {
var mainPanel = button.up('app-main');
var grid = mainPanel.down('grid');
var records = grid.getSelectionModel().getSelection(),
title = records[0].data.title;
var msgText = Ext.String.format(
"Do you really want to delete item '{0}'?",
title
);
msgText = Ext.util.Format.htmlEncode(msgText);
Ext.Msg.confirm(
"Confirmation",
msgText,
function (button) {
if (button != "yes") {
return;
}
grid.store.remove(records);
}
);
},
doFormButton: function (button, action) {
var person = this.getViewModel().get('person');
person.commit();
person.reject();
}
});
В классе контроллера объявлены обработчики кнопок формы и tbar таблицы:
saveItem, addItem, editItem, deleteItem.
Обработчик saveItem имеет код для получения вычисляемого поля модели person и его сохранения в таблице:
var person = this.getViewModel().get('person');
person.commit();
person.reject();
Обработчки addItem имеет код для получения хранилища таблицы из модели
var vm = this.getViewModel();
var store = vm.getStore('persons');
Сортировки записей в таблице по столбцу id:
store.sort({
property: 'id',
direction: 'ASC'
});
Получении последней записи таблицы после сортировки с наибольшим id:
var lastRecord = store.last();
Вставки пустой строки в таблицу:
var record = store.insert(0, {
id: lastRecord.data.id + 1
})[0];
Обработчик editItem заносит значения изменяемой строки таблицы в форму:
В обработчике получают выделенную строку таблицы:
var mainPanel = button.up('app-main');
var grid = mainPanel.down('grid');
var records = grid.getSelectionModel().getSelection();
var record = records[0];
И заносят значения записи в поля формы:
var form = mainPanel.down('form');
var formvm = form.getViewModel();
form.getForm().setValues(record.data);
Обработчик deleteItem удаляет выделенную строку таблицы.
Перед удалением записи таблицы создается диалог подтверждения действия для удаления выделенной строки таблицы:
Ext.Msg.confirm(
"Confirmation",
msgText,
function (button) {
if (button != "yes") {
return;
}
grid.store.remove(records);
}
);
MyApp.view.main.Main:
Ext.define('MyApp.view.main.Main', {
extend: 'Ext.panel.Panel',
xtype: 'app-main',
requires: [
'Ext.plugin.Viewport',
'Ext.window.MessageBox',
'MyApp.view.main.MainController',
'MyApp.view.main.MainModel',
'MyApp.view.main.List',
'MyApp.view.main.Form'
],
controller: 'main',
viewModel: 'main',
layout: 'column',
items: [{
xtype: 'mainlist',
columnWidth: 0.5
}, {
xtype: 'mainform',
columnWidth: 0.5
}]
});
Данный класс определяет главную панель вида с размещенными на ней таблицей и формой:
items: [{
xtype: 'mainlist',
columnWidth: 0.5
}, {
xtype: 'mainform',
columnWidth: 0.5
}]
MyApp.Application:
Ext.define('MyApp.Application', {
extend: 'Ext.app.Application',
name: 'MyApp'
});
Ext.application({
name: 'MyApp',
extend: 'MyApp.Application',
requires: [
'MyApp.view.main.Main'
],
mainView: 'MyApp.view.main.Main'
});
В данном коде объявлен класс приложения и определено его создание с подключением вида:
mainView: 'MyApp.view.main.Main'.
Исходники приложения, а также его работу можно посмотреть на странице:
Количество просмотров: 2216