Главная страница статей --> Хитрости при программировании php, заметки по базам данных

Ajax Master-detail

Источник: realcoding.net

При разработке веб-приложений, отображение информации вида master-detail становится зачастую головной болью. Это особенно касается тех случаев, когда на странице со сложной структурой, отображающей достаточно много "тяжелой" информации (возможно, "поднятой" из многих источников) требуется, чтобы при выборе значения из ниспадающего списка, другой элемент управления среагировал каким-то локальным образом. Например, Label отобразил бы детальное описание выбранного элемента. Или же другой список перезаполнился новыми значениями. Отсылка всей страницы обратно на сервер - это сложный и логически-неверный в данном случае процесс, отнимающий как трафик (считаем размер самой страницы и зачастую монструозный по объемам ViewState), так и увеличивающий нагрузку на сервер (вспомним весь жизенный цикл страницы, инициализацию всех объектов и т.д.).


В данном случае, несомненно, применение асинхронной отправки данных на сервер является наиболее эффективым средством. Наиболее простые примеры отыскать в сети не составляет труда, поэтому я решил рассмотреть немного более сложный и жизненный пример, а именно применение master-detail в стандартном серверном элементе управления ASP.NET DataGrid.
Задача следующая: отобразить таблицу устройств, с возможностью ввода и редактирования записей.



В таблице среди прочих столбцов отображаются:

* название устройства
* модель
* офис/комната

наиболее интересным для нас является именно последний из описываемых столбцов, так как в нём при редактировании записи пользователь выбирает офис из списка имеющихся, после этого перезаполняется нижерасположенный список доступных комнат в данном офисе, где может располагаться редактируемое устройство.



программно это выглядит следующим образом:
на клиенте список офисов представлен так

<asp:DropDownList id=ddlstOffice runat=server Width=100% DataMember=Offices DataSource=<%# dsMain %> DataTextField=ShortDescr DataValueField=G_ID onChange=changeRooms(this.name, this.value); SelectedValue=<%# DataBinder.Eval(Container, DataItem.OfficeID) %>></asp:DropDownList>

где важным является onChange="changeRooms(this.name, this.value);" что при смене вызывает клиентский, зарегистрированный через RegisterClientScriptBlock скрипт со следующим содержанием:

function changeRooms(officeControlName, officeID){
            
AdminEditor.EqEditor.GetRooms(officeControlName, officeID, changeRooms_callback);
}

Единственным назначением данной функции является вызов серверного метода GetRooms класса EqEditor и, соответственно, указание клиентской функции обратного вызова changeRooms_callback.
Серверный метод выглядит следующим образом:

[AjaxPro.AjaxMethod]
       
public DdListStruct GetRooms(string controlID, int officeID)
        {
            
string[] arrstr = controlID.Split(:);
            
ListItemCollection lic = new ListItemCollection();
            if(
Session[Rooms] != null)
            {
               
DataSet ds = new DataSet();
               
ds = (DataSet)Session[Rooms];               
               
                foreach(
DataRow dr in ds.Tables[Rooms].Select(PrimeValue=0 OR OfficeID= + officeID))
                {
                   
ListItem li = new ListItem(dr[ShortDescr].ToString(), dr[G_ID].ToString());
                   
lic.Add(li);

                }
               
            }
            
DdListStruct ddlstr = new DdListStruct(lic, String.Format({0}_{1}_ddlstRoom,arrstr[0], arrstr[1]));
            return
ddlstr;
       }
       
public struct DdListStruct
       
{
            
public DdListStruct(ListItemCollection lic, string controlID)
            {
               
ControlID = controlID;
               
Lic = lic;
            }
            
public string ControlID;
            
public ListItemCollection Lic;
        }

В данном отрывке кода интересными являются следующие детали:
функция возвращает структуру DdListStruct, которая успешно сериализуется компонентой AJAX.Pro и отправляется клиенту. Далее, на клиенте, обращение к полученным данным идет как структурированному объеку (см. код ниже). В большинстве других компонент, да и в том же Atlasе при пересылке данных на клиент, программисту приходится самому заботиться о том, как в серверном коде упаковать данные в строку а затем на клиенте разбирать, т.е. парсить данную строку, получая данные для дальнейшей обработки. Код при этом может получиться довольно громоздким. Да и зачем программисту загружать себя такой неблагодарной работой, лучше потратить время на более полезные вещи. Структура DdListStruct содержит коллекцию элементов (список комнат), которыми будет заполнен элемент управления и собственно, клиентское имя этого элемента управления. Вот тут мы в плотную подошли к тому, зачем на сервер кроме id офиса для которого возвращаем список комнат, еще и передается controlID, т.е. id управляющего элемента. Ответ довольно прост. Для того, чтобы вычислить клиентское имя detail-элемента управления, соответствующего именно управляющему списку, ведь на странице списков может быть много. В приведенном примере это сделано для наиболее распространенного случая, но все же не универсально. Да и такой цели перед собой не ставил, главное это сам подход.

Клиентская функция обратного вызова выглядит следующим образом:

function changeRooms_callback(res){
    var
_struct = res.value;
    var
select_box = document.getElementById(_struct.ControlID);
    if(
select_box != null) {
       
select_box.options.length = 0;
        var
sel = false;
        for (var
i = 0; i < _struct.Lic.length; i++) {
            if(
i==0) sel=true; else sel=false;
            
select_box.options[i] = new Option(_struct.Lic[i].Text, _struct.Lic[i].Value, sel)
        }
    }
}

В данном коде в объектной модели страницы находится список комнат, соответствующий именно тому списку офисов, который пользователь решил отредактировать в данный момент. Далее список очищается и перезаполняется полученными с сервера значениями. Вот и вся механика. Осталось разобраться в еще одном вопросе. Как AJAX master-detail в DataGrid уживается с жизненным циклом страницы. Об этом далее.



Похожие статьи:
- Голосование на PHP своими руками
- Реализация шаблонов на PHP.
- Правда о Сессиях
- Модуль определения географического положения по IP - mod_GeoIP
- Объектно-ориентированное программирование, классы в PHP
- Настройка параметров PHP в php.ini
- Взаимодействие с жизненным циклом страницы
- Система SEO отмирает
- Полезные советы по оптимизации ASP-приложений
- Создание изображений средствами PHP
- Протокол ICQ.v7
- Выпадающие меню с помощью CSS
- Отрисовка связанного дерева с помощью XSLT - как с умом использовать XSLT и XPath


Оглавление | Обсудить на форуме | Главная страница сайта | Карта сайта |

Контакты
Редакция:
[0.005]