пятница, 27 января 2012 г.

"Hello, world!" на Ajax

Я всегда думал про AJAX (Asynchronous Javascript and XML) как про что-то если не сложное, то, как минимум, нетривиальное. И поэтому особо не стремился узнать, как это работает в Oracle APEX и как его взять на вооружение (хотя интерфейс gmail мне очень нравится - ведь могут же люди сделать хорошую страничку, когда захотят). Примеров на просторах world wide web предостаточно, и как только выдалась свободная минутка, я решил этим заняться. Оказалось, что AJAX - это не просто, а очень просто!



Для работы с  AJAX в апексе нужны две вещи: javascript-функция на странице, которая будет обращаться к серверу, и серверная функция, которая будет отвечать на запрос. Для примера сделаем простенькую телефонную книгу: в поле с выпадающим списком будем выбирать имя человека, а в поле ниже будет подгружаться его телефон.

Подготовка

Нам понадобится:
1. Таблица PERSONS с тремя полями: ID, PERSON_NAME, PHONE_NUMBER.
2. Простая HTML страница с одним HTML-регионом и двумя полями: Select List с именем P1_PERSON и Text Area с именем P1_PHONE.
3. В качестве источника данных для списка указываем запрос:
select person_name display_value, id return_value
  from persons
 order by person_name

Процесс со стороны сервера

Заходим в Application Builder -> Shared Components -> Application Processes, нажимаем кнопку Create, после чего запускается мастер создания нового процесса. Большинство свойств оставляем как есть - со значениями по умолчанию. В принципе, для  AJAX-вызова уровня "Hello, world!" достаточно указать название процесса (свойство Name) - GET_PHONE, свойство Process Point - "On Demand" и свойство Source - собственно PL/SQL код процедуры:
declare
  v_phone varchar2(20);
begin
  select phone_number
    into v_phone 
    from persons
   where id = :P1_PERSON; --название поля Select List

  htp.prn(v_phone); -- все, что получит на вход процедура htp.prn, 
                   -- будет передано в качестве ответа вызывающей странице
  exception 
    when others then htp.prn('Во время выполнения запроса произошла ошибка'); 
end; 
Обратите внимание: название процесса чувствительно к регистру! Название процесса в разделе Application Processes должно в точности совпадать с названием, которое будет указано в javascript-функции.


Javascript на вызывающей странице

Идем в Application Builder, открываем нашу страницу, выбираем поле со списком имен P1_PERSON и в разделе Element в поле HTML Form Element Attributes указываем:

onchange="get_phone()"

Теперь при каждом изменении значения в поле  P1_PERSON будет вызываться javascript-функция get_phone().
Далее нажимаем кнопку Apply Changes, возвращаемся к нашей странице и нажимаем кнопку Edit, чтобы отредактировать свойства самой страницы. Там в разделе JavaScript надо написать текст нашей функции:
function get_phone(){

/* Получаем ID человека из выпадающего списка: */
var person_id = document.getElementById('P1_PERSON').value;

/* Создаем объект - вызов ajax.
 GET_PHONE - название процесса в Application Processes 
(и не забываем про регистр!) */
var get = new htmldb_Get(null,html_GetElement('pFlowId').value, 'APPLICATION_PROCESS=GET_PHONE',0);

/* Создаем сессионную переменную P1_PERSON и 
передаем в нее значение, выбранное пользователем: */
get.add('P1_PERSON', person_id);

/* Отправляем запрос и получаем ответ: */
var gReturn = get.get();

/* Полученный ответ помещаем в текстовое поле - элемент P1_PHONE: */
document.getElementById('P1_PHONE').value = gReturn;
}

Теперь можно запустить страницу и наслаждаться результатом!

Небольшое лирическое отступление

Конечно же, когда я делал свой "Hello, World!", у меня были другие поля для ввода, другая таблица с другими полями и немного другие переменные в коде функций. Написанный выше текст работоспособен, но, так как я ОЧЕНЬ ленивый, а сейчас вечер пятницы, я его не запускал. Так что возможно, там где-то могла застрять непереименнованная переменная или еще что-то в том же роде. Если вы найдете ошибку, пожалуйста, сообщите. Если, конечно, вам не лень ;)

UPD. Ошибка все-таки была. В теле PL/SQL функции. Больше ошибок нет, проверено ;).

2 комментария:

  1. Добрый день, спасибо за пост. В данном примере ajax запрос передает только одно значение. Как быть если мне нужно получать
    в js массив данных от сервера?

    ОтветитьУдалить
  2. Браузер обменивается с сервером текстовыми сообщениями, соответственно, вам надо ваш массив сериализовать на сервере и десериализовать в браузере. В качестве формата проще всего взять XML (средства для работы с ним есть и в Oracle, и в javascript) или JSON (в javascript все есть, а для оракла можно найти готовые сторонние пакеты для работы с JSON). Соответственно, вам надо будет дописать PL/SQL код, который упаковывает массив в XML или JSON сообщение, и добавить в javascript функцию кусок, в котором распарсить сообщение и куда-то перенаправить полученный массив.

    ОтветитьУдалить