Создание контроллеров
Контроллер является ключевым звеном, который связывает все части приложения воедино и заставляет их работать. Добавим в каталог BookApp/app/controller файл Books.js со следующим содержанием:
Ext.define('BookApp.controller.Books', { extend: 'Ext.app.Controller', views: ['BookList', 'Book'], stores: ['BookStore'], models: ['Book'], init: function() { this.control({ 'viewport > booklist': { itemdblclick: this.editBook }, 'bookwindow button[action=new]': { click: this.createBook }, 'bookwindow button[action=save]': { click: this.updateBook }, 'bookwindow button[action=delete]': { click: this.deleteBook }, 'bookwindow button[action=clear]': { click: this.clearForm } }); }, // обновление updateBook: function(button) { var win = button.up('window'), form = win.down('form'), values = form.getValues(), id = form.getRecord().get('id'); values.id=id; Ext.Ajax.request({ url: 'app/data/update.php', params: values, success: function(response){ var data=Ext.decode(response.responseText); if(data.success){ var store = Ext.widget('booklist').getStore(); store.load(); Ext.Msg.alert('Обновление',data.message); } else{ Ext.Msg.alert('Обновление','Не удалось обновить книгу в библиотеке'); } } }); }, // создание createBook: function(button) { var win = button.up('window'), form = win.down('form'), values = form.getValues(); Ext.Ajax.request({ url: 'app/data/create.php', params: values, success: function(response, options){ var data=Ext.decode(response.responseText); if(data.success){ Ext.Msg.alert('Создание',data.message); var store = Ext.widget('booklist').getStore(); store.load(); } else{ Ext.Msg.alert('Создание','Не удалось добавить книгу в библиотеку'); } } }); }, // удаление deleteBook: function(button) { var win = button.up('window'), form = win.down('form'), id = form.getRecord().get('id'); Ext.Ajax.request({ url: 'app/data/delete.php', params: {id:id}, success: function(response){ var data=Ext.decode(response.responseText); if(data.success){ Ext.Msg.alert('Удаление',data.message); var store = Ext.widget('booklist').getStore(); var record = store.getById(id); store.remove(record); form.getForm.reset(); } else{ Ext.Msg.alert('Удаление','Не удалось удалить книгу из библиотеки'); } } }); }, clearForm: function(grid, record) { var view = Ext.widget('bookwindow'); view.down('form').getForm().reset(); }, editBook: function(grid, record) { var view = Ext.widget('bookwindow'); view.down('form').loadRecord(record); } });
Теперь разберем код контроллера. Во-первых, мы наследуем его от класса Ext.app.Controller
и устанавливаем для контроллера ранее созданные представления, модели и хранилища:
views: ['BookList', 'Book'], stores: ['BookStore'], models: ['Book'],
Далее в параметре init
с помощью функции мы инициализируем обработчики кнопок, которые у нас находятся в представлении.
Связать обработчики с компонентами помогает функция control
. Эта функция использует класс Ext.ComponentQuery
,
который позволяет с помощью селектор в стиле CSS найти элементы. Например, выражение 'viewport > booklist'
ищет элементы с псевдонимом
booklist, которые определены в компоненте viewport. Данный селектор будет в итоге получать представление BookList.
А выражение 'bookwindow button[action=new]'
получит кнопку button, у которой свойство action имеет значение new и которая
находится в элементе bookwindow, то есть в представлении Book, которое имеет псевдоним bookwindow. Таким образом, если вы знакомы с селекторами
CSS, то вам не составит труда в понимании работы селекторов и в ExtJS.
Далее мы связываем найденные по селекторам компоненты с обработчиками. Например, у грида мы определяем обработчик двойного нажатия
(параметр itemdblclick
) на строку:
'viewport > booklist': { itemdblclick: this.editBook }
Все функции обработчиков определены после функции init
. Обработчик this.editBook
загружает выбранную модель в
окно:
editBook: function(grid, record) { var view = Ext.widget('bookwindow'); view.down('form').loadRecord(record); }
С помощью метода Ext.widget
мы находим нужный компонент по селектору Ext.ComponentQuery (этот выражение было бы аналогично выражению Ext.create('widget.bookwindow')
) и затем получаем его дочерний элемент с помощью метода
down
, также по селектору. И далее загружаем в форму выбранную модель.
После загрузки модели мы можем воспользоваться тремя возможностями: добавить новую книгу, изменить выбранную или удалить выбранную. И тут в дело вступают обработчики этих кнопок. Поскольку обработчики однотипны, разберем один из них.
Обработчик updateBook получает данные измененной книги и отправляет ajax-запрос на сервер:
updateBook: function(button) { var win = button.up('window'), form = win.down('form'), values = form.getValues(), id = form.getRecord().get('id'); values.id=id; Ext.Ajax.request({ url: 'app/data/update.php', params: values, success: function(response){ var data=Ext.decode(response.responseText); if(data.success){ var store = Ext.widget('booklist').getStore(); store.load(); Ext.Msg.alert('Обновление',data.message); } else{ Ext.Msg.alert('Обновление','Не удалось обновить книгу в библиотеке'); } } }); },
Обработчик в качестве параметра получает нажатую кнопку и затем, используя метод up
мы можем получить родительские элементы по отношению к этой кнопке:
function(button) {var win= button.up('window')...
Выражением values = form.getValues()
мы получаем все значения полей формы, но поскольку при изменении при взаимодействии с бд, например,
требуется id, то затем добавляем к переменной values еще и id обновляемой модели.
Далее отправляем ajax-запрос с новыми данными книги на сервер, передавая запросу в качестве параметра переменную values. Принимающий файл update.php (который, как предполагается, находится в папке BookApp/app/data) мог бы так получать переданные параметры:
<?php $id = $_POST['id']; $name = $_POST['name']; $author = $_POST['author']; $year = $_POST['year']; // далее проводим обработку полученных данных echo '{ "success": true, "message":"Книга: ' . $id . '. ' . $name . ' (' . $author . ') обновлена"}'; ?>
И в конце в функции success
мы смотрим на результат, который посылает в ответ сервер, и если все прошло успешно, то
загружаем обновленные данные с сервера.
По похожему принципу действуют остальные два обработчика.
И в самом конце изменим файл приложения app.js, чтобы он принимал созданный выше контроллер следующим образом:
Ext.application({ requires: ['Ext.container.Viewport'], name: 'BookApp', appFolder: 'app', controllers: ['Books'], launch: function() { Ext.create('Ext.container.Viewport', { layout: 'fit', items: { xtype: 'booklist' } }); } });
В свойстве controllers: ['Books']
указываем созданный выше контроллер.
Теперь приложение готово и его можно запускать:
Таким образом, мы можем применять паттерн MVC к построению приложений на Ext JS.