Создание контроллеров

Контроллер является ключевым звеном, который связывает все части приложения воедино и заставляет их работать. Добавим в каталог 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.

    Поддержать сайт на родительском проекте КГБ