jqGrid для Raudus

в 9:14, , рубрики: Delphi, jqgrid, jquery, метки: ,

Целью данной статьи не является введение в технологии или инструменты разработчика, которые в ней так или иначе упоминаются, основная цель — это дать небольшой толчок тем, кто этими технологиями или инструментами только начинает интересоваться и хотел бы понять, будут ли они полезны и покроют ли они все текущие потребности. Однако, несмотря на это, я хотел бы сказать несколько вступительных слов о Raudus.

Сталкивались ли вы с задачей переписать код достаточно успешного и уже давно используемого Windows приложения, написанного на Delphi, с тем, чтобы превратить его в Web приложение, но при этом ограничиться минимальным числом изменений исходного кода? Если да, то эта статья для вас. Есть несколько способов решить данную задачу, однако я хотел бы остановится на одном из них. Имя ему — Raudus.

Raudus — это web-framework и набор компонентов для Delphi, позволяющий создавать Rich Internet Applications (RIA). При этом сам процесс разработки мало чем отличается от разработки обычного desktop приложения. Предоставляемый при этом набор визуальных компонентов содержит аналоги большинства стандартных для Delphi компонентов — так называемый Raudus VCL. Вы используете эти визуальные компоненты, а также привычные вам невизуальные (например, компоненты прямого доступа к СУБД), и компилируете консольное приложение, которое выполняется как HTTP-сервер. По сути вся логика вашего приложения остаётся на стороне этого сервера, а визуальная часть, то бишь GUI, переносится в браузер пользователя. Потребности общения визуальной клиентской части и серверной части при этом полностью покрываются возможностями AJAX. Более подробно останавливаться на описании данного решения я не буду. На сайте Raudus есть небольшие примеры, также вы можете свободно скачать библиотеку компонентов Raudus, установить её и попробовать запустить примеры, которые идут в комплекте.

И всё же в моём случае стандартного набора компонентов оказалось недостаточно. Например, очень хотелось использовать полнофункциональный аналог TDBGrid: с фильтрами, с сортировкой, с colspan, с paging и т.д. Сразу же первым на ум пришёл jqGrid. Но как его заставить «внедриться» в Raudus и возможно ли это вообще?

К счастью, в крайних версиях Raudus присутствует специальный класс TRaExtendableControlGCD, наследуя который потенциально можно преобразовать любой jQuery UI компонент, jQuery плагин, а также компоненты из состава ExtJS, QooxDoo и др. в компонент Raudus. При этом выглядеть новоявленный компонент будет одинаково, как в DesignTime, так и в RunTime.

Класс TRaExtendableControlGCD имеет три ключевых метода: RaDrawExtend, RaUpgradeExtend и RaRouteExtend, переопределяя которые вы по сути пишете оболочку вокруг, например, jqGrid, чтобы Raudus «понимал» как с этим компонентом работать.
RaDrawExtend — переопределяя этот метод, вы пишете JavaScript-код, инициализирующий jqGrid.
RaRouteExtend — переопределяя этот метод, вы пишете код, который должен выполняться при каком-то действии в клиентской части компонента jqGrid. Т.е. это место реакции на какой-либо AJAX-запрос со стороны jqGrid.
RaUpgradeExtend — переопределяя этот метод, вы пишете JavaScript-код, который должен выполниться после кода в методе RaRouteExtend. Т.е. это место обратного воздействия серверной части компонента на клиентскую часть компонента.
Как в общих чертах использовать эти три метода и что из этого получается вы можете подсмотреть в примерах, поставляемых вместе с дистрибутивом Raudus. Там, в частности, содержатся примеры встраивания jqDatePicker и TinyMCE.

Самое первое и очевидное, что необходимо реализовать в случае с jqGrid, — это заполнение его данными и организация paging. Как же это сделать в данном случае?

Известно, что jqGrid поддерживает несколько datatype (способов получения данных): json (jsonstring), xml (xmlstring), local, javascript и function. function позволяет указать в качестве источника получения данных функцию javascript, а внутри этой функции можно выполнить запрос данных с серверной части приложения, затем воспользоваться методом addJSONData, чтобы заполнить jqGrid полученными данными. Этим способом мы и воспользуемся.

Итак, в строке инициализации jqGrid мы указываем datatype и определяем функцию, в которой будет происходить запрос начальной и очередной порции данных:

Развернуть/Свернуть код

  AJavascript :=

    'var me=this;' +

    'me.onRender=function(){' +
      // load jQuery library or ensure it is already loaded
      'me.r=me.require(["js","/jquery-1.10.1/jquery-1.10.1.min.js"],function(){' +
        'me.r=me.require(["js","/jquery.jqGrid-4.5.2/js/jquery.jqGrid.min.js",' +
                         '"js","/jquery.jqGrid-4.5.2/js/i18n/grid.locale-ua.js",' +
                         '"css","/jquery.jqGrid-4.5.2/css/ui.jqgrid.css",'+
                         '"css","/jquery-ui-1.10.3/themes/base/minified/jquery-ui.min.css"],function(){' +

          'me.r=undefined;' +
          'me.d=setTimeout(function(){' +
            'me.d=undefined;' +

            'if(typeof jQuery==="undefined"){' +
              'me.getDOM().innerHTML="jQuery library was not loaded";' +
              'return;' +
            '};' +
            'if(typeof $.fn.jqGrid==="undefined"){' +
              'me.getDOM().innerHTML="jqGrid Class was not loaded";' +
              'return;' +
            '};' +

            'me.e=document.createElement("table");' +
            'me.e.id="grid' + IntToStr(ID) + '";' +
            'me.getDOM().appendChild(me.e);' +
            'me.p=document.createElement("div");' +
            'me.p.id="pager' + IntToStr(ID) + '";' +
            'me.getDOM().appendChild(me.p);' +

            'function getData(postdata){' +
              'me.route(JSON.stringify(postdata));' +
            '};' +

            '$(me.e).jqGrid({' +
              'datatype:getData,' +
              ...
              'rowNum:25,'+
              'pager:"#"+me.p.id,'+
              'caption:"jqGrid"' +
            '});' +
          '},0);' +

        '});' +
      '});' +
    '};' +
    ...

Метод me.route внутри нашей функции getData — это и есть способ обращения клиентской части компонента к серверной части с помощью AJAX. Таким образом, мы запрашиваем у серверной части набор данных на основании параметров, содержащихся в postdata. Все параметры запроса при этом упаковываются в JSON строку. postdata содержит служебные параметры запроса данных, которые описаны в документации jqGrid, среди них: текущий номер страницы с очередной порцией данных, количество записей в порции данных, параметры сортировки, фильтра и т.д. На серверной стороне при этом срабатывает метод RaRouteExtend, в котором мы обрабатываем присланные параметры запроса, формируем необходимую порцию данных в виде JSON строки и отдаём эту порцию обратно в jqGrid в методе RaUpgradeExtend примерно вот таким образом:

    AJavascript := AJavascript +
      'var me=this;' +
      'if(me.e){' +
        'var v=JSON.parse('''+FJSON+''');'+
        '$(me.e)[0].addJSONData(v);' +
      '};';

где FJSON — это порция данных, представленная в виде JSON строки.

Итак, что происходит при первом обращении:
1. Пользователь впервые загружает форму с jqGrid. Выполняется серверный метод RaDrawExtend, происходит инициализация jqGrid.
2. jqGrid выполняет javascript функцию getData() для получения первой порции данных.
3. Выполняется серверный метод RaRouteExtend. Формируется набор данных на основании параметров запроса данных, в которых указано, что запрашивается первая страница данных (page=1). Набор данных сериализуется в JSON строку.
4. Выполняется серверный метод RaUpgradeExtend, в котором прописывается javascript код, добавляющий данные в jqGrid.
5. Выполняется javascript код, прописанный в методе RaUpgradeExtend и jqGrid наполняется данными.

Что происходит при переходе на страницу с очередной порцией данных:
1. Пользователь переходит на следующую страницу с данными в jqGrid.
2. jqGrid снова выполняет javascript функцию getData() для получения очередной порции данных.
3. Выполняется серверный метод RaRouteExtend. Формируется набор данных на основании параметров запроса данных, в которых указано, что запрашивается очередная страница данных (page=2, page=3 и т.д.). Набор данных сериализуется в JSON строку.
4. Выполняется серверный метод RaUpgradeExtend, в котором прописывается javascript код, добавляющий данные в jqGrid.
5. Выполняется javascript код, прописанный в методе RaUpgradeExtend и jqGrid наполняется данными.

Вот, собственно, и всё. Если возникли какие-то вопросы, задавайте. Возможно в статью придётся добавить ряд уточнений.
Спасибо за внимание и успехов вам!

Автор: fandm

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js