Конечно, мы хотим иметь возможность не только отображать данные, но и изменять их. В этом посте мы будем использовать графический интерфейс PicoLisp для отображения данных и включения их модификации в HTML-форму.
На первом этапе мы просто создадим страницу, которая позволит нам отображать данные и переходить между записями:
Настройка файла
Структура программы строится на основе предыдущего поста, который используется в качестве основы. Мы будем использовать этот файл и расширять его.
Создадим новую функцию person
и добавим ее в скрипт allowed
. Также запустим с ее помощью сервер. Остальное остается без изменений. Назовем новый файл family-edit.l
.
### Modify / add following lines:
(allowed ("css/")
"@lib.css" "!treeReport" "!person")
...
(de person ())
...
(de go ()
(rollback)
(server 8080 "!person") )
Функция person
должна быть функцией, в которой мы можем отобразить все необходимые данные о записи (т.е. человеке) одним взглядом. Мы хотим отображать данные в виде поля формы и иметь возможность переключаться между режимом чтения и редактирования с помощью кнопки «Редактировать».
Первое, что нам нужно, это создать стандартную HTML-функцию, включающую запуск сессии. На этой странице мы не будем использовать CSS-классы bootstrap, потому что мы будем использовать множество предопределенных функций PicoLisp gui, которые не очень хорошо работают с Bootstrap.
(de person ()
(app)
(action
(html 0 "Person" "@lib.css" NIL
(form NIL
]
Скобка ]
закрывает все открытые круглые скобки. Это может быть полезно при разработке.
Как и в предыдущих примерах, мы можем запустить ее с помощью $ pil family-edit.l -family~main -go +
и когда мы направим браузер на http://localhost:8080, мы должны увидеть пустую вкладку с заголовком «Person».
Получение элемента базы данных
Как форма «узнает», какой элемент базы данных мы хотим отобразить? Это контролируется вызовом функции <id>
где-то внутри формы. <id>
связывает вывод с глобальной переменной *ID
. Поэтому нам нужно сделать две вещи:
- Добавление
<id>
в нашу форму, - добавление параметра
*ID
к URL.
Например, мы можем вызвать <id>
в заголовке нашей формы. ( <id> (: nm ))
установит *ID
на текущий объект и отобразит его имя.
(form NIL
(<h2> NIL (<id> (: nm)))
Если теперь мы направим браузер на http://localhost:8080/?*ID=-A1, то увидим следующее:
Префиксный класс +E/R
.
Теперь, когда мы указали текущий объект, мы можем отобразить его данные в форме. Для доступа к объекту базы данных мы будем использовать префиксные классы +E/R
и +Obj
.
Читайте здесь введение в графический интерфейс формы PicoLisp и здесь подробнее о префиксных классах.
Точно так же, как мы можем добавлять стили с помощью +Styles
и привязывать переменные к элементу GUI с помощью +Val
, мы можем подключить сущность базы данных с помощью класса +E/R
. Синтаксис довольно прост:
(gui '(+E/R +TextField) '(nm : home obj) 40 "Name")
Это создает текстовое поле, которое связано со свойством nm
(«имя») объекта home obj
. Объект home obj
— это объект, принадлежащий текущей форме, то есть запись, указанная через глобальную переменную *ID
.
Аналогичным образом мы можем получить дату рождения и смерти:
"born" (gui '(+E/R +DateField) '(dat : home obj) 10)
"died" (gui '(+E/R +DateField) '(fin : home obj) 10)
Элемент формы +ClassField
Элемент формы +ClassField
можно использовать для отображения и изменения класса объекта. Например, в данном примере отображается выпадающее меню, которое показывает в качестве текущего значения либо «Male», либо «Female»:
(gui '(+ClassField) '(: home obj) '(("Male" +Man) ("Female" +Woman))) )
Префиксный класс +Obj
Префиксный класс +Obj
используется для хранения определенного объекта. Таким образом, объект DB становится элементом GUI первого класса, так же как и примитивы string, number и т.д. Кроме того, +Obj
предоставляет предложения из базы данных, используя dbHint
.
Что это значит? Возьмем для примера поле «Партнер человека». Партнер человека — это тоже объект, связанный свойством mate
. Поскольку мы используем +Obj
, мы можем получить доступ к имени записи следующим образом:
(gui '(+E/R +Obj +TextField) '(mate : home obj) '(nm +Person) 30) )
+Obj
также предлагает две приятные дополнительные функции:
- Предложения, если мы хотим изменить имя партнера (мы увидим это позже в режиме редактирования!),
- Карандаш, который выполняет предопределенную функцию, если мы нажмем на него. Если функция не указана, используется метод
url>
.
Допустим, мы хотим видеть обзор записей партнера, когда мы нажимаем на карандаш. Другими словами, мы хотим изменить *ID
в URL на запись партнера.
Давайте определим метод url>
, который делает именно это в нашей модели класса +Person
:
### DB ###
(class +Person +Entity)
(rel nm (+Need +Sn +Idx +String)) # Name
...
(rel txt (+String)) # Info
(dm url> (Tab)
(list "!person" '*ID This) )
url>
принимает аргумент (Tab)
, указывающий, какая вкладка должна быть открыта (что, очевидно, интересно только в приложении с несколькими вкладками — не так много в нашем одностраничном приложении).
Вы можете увидеть результат в анимированном GIF выше: когда мы нажимаем на ручку, страница перескакивает для отображения этой записи.
Создание таблицы с помощью +Chart
и <table>
Как уже было показано в примере приложения To-Do App, мы можем использовать +Chart
в сочетании с <table>
для отображения данных в сетке вместе с некоторыми предопределенными кнопками действий.
Сначала мы определяем данные, используемые в диаграмме, которые являются свойством kids
текущего объекта. +Chart
ожидает числовой аргумент в виде количества столбцов. Кроме того, мы можем вызвать две функции: Первая вызывается, когда график заполняется данными, вторая — когда данные считываются.
(gui '(+E/R +Chart) '(kids : home obj) 7
'((This) (list NIL This (: dat) (: pa) (: ma)))
cadr )
Что это значит?
-
'((This) (list NIL This (: dat) (: pa) (: ma)))
создает список списков из данных(kids : home obj
, то есть ровно по одному значению на столбец и строку.
Это может быть немного запутанным, но все должно проясниться, если вы проверите фактический вывод таблицы и ее функцию.
После того как мы определили входное значение, мы можем определить таблицу. Функция <table>
принимает аргументы «attributes», «title», «head» и «program». Давайте установим атрибуты и заголовок в NIL
и определим head как:
(<table> NIL NIL
'(NIL (NIL "Children") (NIL "born") (NIL "Father") (NIL "Mother"))
Затем создадим поля ввода, как указано выше:
(do 6
(<row> NIL
(choPerson 1)
(gui 2 '(+Obj +TextField) '(nm +Person) 20)
(gui 3 '(+Lock +DateField) 10)
(gui 4 '(+ObjView +TextField) '(: nm) 20)
(gui 5 '(+ObjView +TextField) '(: nm) 20)
(gui 6 '(+DelRowButton))
(gui 7 '(+BubbleButton)) ) )
(<row> NIL NIL (scroll 6 T)) )
Пожалуйста, пока не обращайте внимания на choPerson
, мы вернемся к этому в следующем посте.
Таблица вывода готова!
Давайте применим немного форматирования. В PicoLisp есть встроенная функция <grid>
, которая форматирует в строки и столбцы, подобно таблице. Каждые четыре «элемента» будут размещены в одной строке, а ширина определяется самым длинным элементом.
(<grid> 4
"Occupation" (gui '(+E/R +TextField) '(job : home obj) 20)
"Father" (gui '(+E/R +Obj +TextField) '(pa : home obj) '(nm +Man) 30)
"born" (gui '(+E/R +DateField) '(dat : home obj) 10)
"Mother" (gui '(+E/R +Obj +TextField) '(ma : home obj) '(nm +Woman) 30)
... )
Установка начальной точки по умолчанию
Наконец, давайте определим начальную точку по умолчанию для нашего приложения. Это означает, что запись по умолчанию должна загружаться, когда мы направляем браузер на http://localhost:8080.
Как мы можем это сделать? Прежде всего, нам нужно установить val
нашей глобальной переменной *DB
, например, на запись {A12}
(Queen Elizabeth). В программе REPL:
$ family-edit.l -family~main +
family: (set *DB '{A12})
-> {A12}
family: (show *DB)
{1} {A12}
+Woman {3}
+Person {2}
+Man {4}
-> {1}
Далее, давайте загрузим это значение как *ID
по умолчанию при запуске сессии. Сессия также должна запускаться сразу при загрузке страницы.
(when (app)
(redirect (baseHRef) *SesId *Url "?*ID=" (ht:Fmt (val *DB))) )
Теперь мы также можем динамически изменить наш html-заголовок на имя человека:
html 0 (; *ID nm) "@lib.css" NIL
Таким образом, при посещении сайта http://localhost:8080 мы попадаем непосредственно на запись королевы Елизаветы.
Таким образом, мы получаем все данные записи в понятном и удобном для пользователя формате. Однако все поля ввода отключены, и мы не можем сохранить какие-либо изменения.
Давайте посмотрим, как это изменить в следующем посте.
Исходный код до этого момента вы можете найти здесь.
Исходники
- https://software-lab.de/doc/index.html
- https://software-lab.de/doc/app.html