Alterator/Master Class: различия между версиями

Материал из ALT Linux Wiki
мНет описания правки
м (→‎Поле ввода: мелкая вычитка)
 
(не показано 20 промежуточных версий 3 участников)
Строка 4: Строка 4:


=== Текстовые поля и надписи ===
=== Текстовые поля и надписи ===
==== Поле ввода ====
Самым первым и самым простым применением может быть редактирование конфигурационного файла
Самым первым и самым простым применением может быть редактирование конфигурационного файла
в формате Param: value
в формате Param: value


Предположим, на экране мы хотим получить такую форму
Предположим, на экране мы хотим получить такую форму:


[[Файл:Label_and_textinput.png]]
[[Файл:Label_and_textinput.png]]


В файле index.html нашего модуля пишем:
В файле index.html нашего модуля пишем:
<pre>
<source lang="html4strict">
  <span translate="_">Server name:</span>&nbsp;
  <span translate="_">Server name:</span>&nbsp;
  <input type="text" class="text" name="your_server" style="width:120px;"/>
  <input type="text" class="text" name="your_server" style="width:120px;"/>
</pre>
</source>
Если строка '''Server name:''' определена в файле переводов, то она будет переведена.
Если строка '''Server name:''' определена в файле переводов, то она будет переведена.
Ни изменять значение, ни читать его мы больше не будем.
Ни изменять значение, ни читать его мы больше не будем.


Поле ввода имеет имя ''your_server'' по которому можно обращаться к данному полю.
Поле ввода имеет имя ''your_server'', по которому можно обращаться к данному полю.
Писать или читать его значение.
Писать или читать его значение.
Для того, чтобы записать значение '''127.0.0.1''' в это поле, в файле ajax.scm пишем:
Для того, чтобы записать значение '''127.0.0.1''' в это поле, в файле ajax.scm пишем:
<source lang="lisp">
  (form-update-value "your_server" "127.0.0.1")
  (form-update-value "your_server" "127.0.0.1")
</source>


Для того, чтобы прочитать значение из поля, в файле ajax.scm пишем
Для того, чтобы прочитать значение из поля, в файле ajax.scm пишем
  (form-value "your_server")
<source lang="lisp">
  (form-value "your_server" )
</source>


В более сложном виде, для передачи значения в backend пишем, например, так:
В более сложном виде для передачи значения в backend по имени ''backend_name'' пишем, например, так:
<source lang="lisp">
  (catch/message
  (catch/message
         (lambda()
         (lambda()
         (woo "new" "/backend/" 'server (form-value "your_server") 'language (form-value "language"))))
         (woo "new" "/backend_name/" 'server (form-value "your_server") 'language (form-value "language"))))
</source>
В этом случае в backend передаются параметр server и значение form-value "your_server",  
В этом случае в backend передаются параметр server и значение form-value "your_server",  
а так же language и form-value "language" для возможности правильного перевода.
а также language и form-value "language" для возможности правильного перевода.


Более удобным является использование
Более удобным является использование
<source lang="lisp">
  (form-value-list '("field1" "field2" "field3" "field4")
  (form-value-list '("field1" "field2" "field3" "field4")
</source>
В этом случае передаются пары значений ''имя_поля'' ''значение_поля''
В этом случае передаются пары значений ''имя_поля'' ''значение_поля''


Каким образом мы получим значение нашего параметра в backend, в данной статье рассматриваться не будет. Предположим, что значение мы получили и нам осталось выполнить вызов
Каким образом мы получим значение нашего параметра в backend, в данной статье рассматриваться не будет. Предположим, что значение мы получили и нам осталось выполнить вызов
write_string_param param_name param_value
<source lang="bash"> write_string_param param_name param_value</source>
В нашем случае
В нашем случае
write_string_param your_server your.domain.com
<source lang="bash"> write_string_param your_server your.domain.com</source>


Теперь, обратимся к backend-у, иначе он нам сам ни чего отдавать не будет.
Теперь обратимся к backend-у, иначе он нам сам ничего отдавать не будет.
В ajax.scm пишем функцию
В ajax.scm пишем функцию
(form-update-value "your_server" (woo-read "/backend_name"))
<source lang="lisp"> (form-update-value "your_server" (woo-read "/backend_name"))</source>
Или более универсальный вариант
Или более универсальный вариант
(form-update-value-list (woo-read-first "/backend_name"))
<source lang="lisp"> (form-update-value-list (woo-read-first "/backend_name"))</source>
В этом случае имена параметров должны иметь такие же имена, как и имена в формах.
В этом случае имена параметров должны иметь такие же имена, как и имена в формах.


==== Именованные метки ====
В рассмотренном выше примере мы не могли изменить надпись возле поля ввода.
Если нам такая функциональность нужна, то можно использовать
''<span class="alterator-label" name="label_name"/>''
Разместим в файле index.html такой фрагмент
<source lang="html4strict">
<span translate="_">Used base:</span>&nbsp;
<u><span class="alterator-label" name="base_"/></u>&nbsp;
<span translate="_">on host</span>&nbsp;
<u><span class="alterator-label" name="host_"/></u>
</source>
В файле ajax.scm создадим функцию
<source lang="lisp"> (define (constr_string)
  (let* ((data (woo-read "/backend_name/string" ))
        (cur_base (and (pair? data) (woo-get-option (car data) 'base)))
        (cur_host (and (pair? data) (woo-get-option (car data) 'host)))
        )
      (form-update-value "base_" cur_base)
      (form-update-value "host_" cur_host) ))
</source>
Которая установит нам нужные значения, при условии, что backend вернет нам пары значений.
В результате у нас получилась такая строка
[[Файл:Constructed_string.png]]
=== Кнопки, радиокнопки и переключатели ===
==== Кнопки ====
==== Группа радиокнопок (radio) (переключатель с единственным выбором, '''"ИЛИ"''') ====
Чтобы наши радиокнопки переключались, они все должны иметь одинаковое имя.
Разместим в форме набор радиокнопок.
Все они имеют одинаковое имя (''use_src''), но разные ''"value"''.
Рядом с кнопками разместим надписи, для выравнивания используем таблицу (в примере не показано).
<source lang="html4strict">
<input type="radio" name="use_src" value="system" checked="#f"/>
<input type="radio" name="use_src" value="local" checked="#t"/>
<input type="radio" name="use_src" value="localldap" checked="#f"/>
<input type="radio" name="use_src" value="remoteldap" checked="#f"/>
</source>
Одна из кнопок включена по умолчанию.
Это выглядит так:
[[Файл:Radiobutton_group.png]]
Вызов ''(form-value "use_src")'' в ajax.scm вернет вам значение той радиокнопки, которая в данный момент выбрана, а ''(form-update-value "use_src" "system")'' установит радиокнопку с value="system" в включенное состояние.
Нам остается только узнать, какую из радиокнопок включать у backend-а.
<source lang="lisp">
(form-update-value "use_src" (woo-read "/backend" ))
</source>
Полезным бывает обработать изменение состояния группы переключателей без обращения к backend-у.
Для этого в удобном нам месте напишем
<source lang="lisp">
(form-bind "use_src" "change" set_src)
</source>
а в функции set_src - нужные действия.
====Группа чекбоксов (checkbox). (Переключатель с множественным выбором '''"И"''').====
Есть два варианта реализации данного механизма:
* Таблица класса '''alterator-checklistbox'''
* Набор переключателей, формируемый вручную.
Для создания таблицы в index.html пишем
<source lang="html4strict">
<table class="alterator-checklistbox" name="checklistbox"/><br/>
</source>
Для заполнения таблицы в файле ajax.scm пишем функцию
<source lang="lisp">
(form-update-enum "checklistbox"
        (woo-list "/backend/checklistbox" 'language (form-value "language")))
</source>
Можно для чтения списка передать набор параметров, так же, как и '''language (form-value "language")''
При этом, в backend результат возвращается при помощи вызова
<source lang="bash">
write_enum_item "$name" "$label"
</source>
Если "$label" не передается, то в качестве значения используется "$name"
После того, как список заполнен, необходимо установить некоторые чекбоксы в состояние "включено".
Для этого используется
<source lang="lisp">
(form-update-value  "checklistbox" '("список_имен_которые_нужно_включить"))
</source>
В результате, на экране, мы получим примерно такой набор:
[[Файл:CheckBox_group.png]]
Создание набора, формируемого вручную несколько сложнее, в плане дизайна и размещения элементов в форме.
В файле index.html, в таблице, или как будет удобно, размещаем набор переключателей
(Как разместить метки рядом с переключателем, надеюсь, понятно.)
<source lang="html4strict">
<input type="checkbox" name="local" value="#t"/>
<input type="checkbox" name="enable_tls" value="#t"/>
<input type="checkbox" name="local_and_tls" value="#t"/>
</source>
Включаем (если нужно) состояние по умолчанию.
В файле ajax.scm определяем функцию
<source lang="lisp">
(define (read_ports)
    (form-update-value-list
      '("local" "enable_tls" "local_and_tls") (woo-read-first "/openldap/config")))
</source>
которая установит нам все переключатели в нужное состояние, если backend нам правильно ответит.
Правильный ответ backend-а определяется вызовом ''write_bool_param''
Например:
<source lang="bash">
  if [ "${url/ldap:\/\/localhost\/[[:space:]]ldaps:\/\/\//}" != "$url" ];then
    write_bool_param 'local_and_tls' 'yes'
    write_bool_param 'local' 'no'
    write_bool_param 'enable_tls' 'no'
  fi
</source>
В результате, на экране получится
[[Файл:CheckBox_group_main.png]]
=== Списки ===
==== Выпадающий список (select)====
Набор значений для выпадающего списка можно задать непосредственно в форме,
равно как и получить от backend-а.
В случае, если набор значений заранее не определен, то только из backend-а.
Разместим в форме такой код:
<source lang="html4strict">
<span translate="_">Shell:</span>
<select name="loginshell"/>
</source>
Список пуст. Надпись будет переведена.
В файле ''ajax.scm'' определим функцию заполнения списка значениями, получаемыми от backend-а.
<source lang="lisp">
(form-update-enum "loginshell" (woo-list "/backend_name/shell"))
</source>
В backend-е пишем, к примеру, так:
<source lang="bash">
#!/bin/sh
po_domain="alterator-test"
alterator_api_version=1
. alterator-sh-functions
list_shell(){
    write_enum_item "/sbin/nologin"
    while read sh; do
        [ -x "$sh" ] || continue
        write_enum_item "$sh"
    done </etc/shells
}
on_message() {
  case "$in_action" in
    read)
    ;;
    write)
    ;;
    list)
        case "$in__objects" in
            shell)
                list_shell
            ;;
        esac
    ;;
  esac
}
message_loop
</source>
Проверяем наш backend,
# alterator-cmdline /backend_name/shell action list
name:/sbin/nologin
label:/sbin/nologin
name:/bin/sh
label:/bin/sh
name:/bin/bash
label:/bin/bash
name:/bin/ash
label:/bin/ash
name:/bin/bsh
label:/bin/bsh
Проверяем работу формы. Видим [[Файл:Select.png]]
=== Таблицы ===
=== Изображения ===
Для добавления изображения в форму достаточно добавить
<source lang="html4strict">
<img class="alterator-img" name="image_name"/>
</source>
Каким-либо способом получить путь к файлу изображения относительно каталога
{{path|/usr/share/alterator/design/images/}}
и вызвать (form-update-value «image_name» «image_path»)
Пример использования есть в разделе '''Изменяющиеся иконки'''
=== Динамические формы ===
==== Видимость элементов ====
Предположим, часть элементов формы имеет отношение к некоторому состоянию переключателя.
Создадим форму следующего содержания
<source lang="html4strict">
<html wf="none">
    <body>
        <form method="POST">
        <input type="checkbox" name="mode" checked="#t"/>&nbsp;
        <b><span translate="_">Show area</span></b>
        <hr/>
        <p>Этот текст будет отображаться постоянно</p>
        <div name="hidden_area" style="display:inline">
            <b>После выключения опции текст в этой области будет скрыт</b>
        </div>
        <p>И этот текст будет отображаться постоянно</p>
        </form>
    </body>
</html>
</soutce>
При старте формы область"hidden_area" будет видна. Теперь, после переключения режима,
эта область должна скрыться.
Для этого, в ajax.scm включим обработчик события
<source lang="html4strict">
(form-bind "mode" "change" change_mode)
</source>
и напишем функцию ''change_mode''
<source lang="html4strict">
(define (change_mode)
        (form-update-visibility '("hidden_area") (form-value "mode")))
</source>
Чекбокс включен:  [[Файл:Din_area1.png]]
Чекбокс выключен: [[Файл:Din_area2.png]]
Естественно, вместо одной строки текста можно скрывать много всяких элементов формы.
==== Доступность элементов ====
==== Изменяющиеся иконки ====
Наша задача отобразить некоторое состояние системы пикрограммой.
Состояние системы можно получить от backend-а или от элементов управления.
Приведем минимальный пример index.html
<source lang="html4strict">
<html wf="none">
  <body>
    <form method="POST">
        <input type="radio" name="set_status" value="locked" checked="#t"/>&nbsp;
        <span translate="_">Lock this</span><br/>
        <input type="radio" name="set_status" value="unlocked" checked="#f"/>&nbsp;
        <span translate="_">UnLock this</span><br/>
        <img class="alterator-img" name="status"/>
    </form>
  </body>
</html>
</source>
Изменение состояния радиокнопок должно отобразиться иконкой, но ее src не указан.
В файле ajax.scm пишем
<source lang="lisp">
(define-module (ui test ajax)
    :use-module (alterator ajax)
    :use-module (alterator str) ;; Нужно для работы string-append
    :use-module (alterator woo)
    :export (init))
(define (set_status)
    (form-update-value "status" (string-append "test/"
        (car (string-cut-repeated (or (form-value "set_status") "unlocked") #\,))
        ".png")))
(define (init)
    (set_status)
    (form-bind "set_status" "change" set_status)
)
</source>
Функция
(string-append "test/" (car (string-cut-repeated (or (form-value "set_status") "unlocked") #\,))  ".png")
соберет нам строку вида ''"test/locked.png"'' и передаст ее в качестве аргумента для '''form-update-value'''
И вот результат
[[Файл:Locked.png]] <--> [[Файл:Unlocked.png]]
== См. также ==
* <DPL>
  namespace =
  titlematch = Alterator
  nottitlematch = Alterator/%
  mode = inline
  inlinetext=&nbsp;&bull;&#32;
</DPL>


* <DPL>
  namespace =
  titlematch = Scheme/Tutorial
  mode = inline
  inlinetext=&nbsp;&bull;&#32;
</DPL>


[[Категория:Alterator]]
{{Category navigation|title=Alterator|category=Alterator|sortkey=*}}

Текущая версия от 15:44, 17 марта 2015

Пошаговые примеры

создания и использования различных виджетов Alterator для форм html, и, может быть, Qt версий.

Текстовые поля и надписи

Поле ввода

Самым первым и самым простым применением может быть редактирование конфигурационного файла в формате Param: value

Предположим, на экране мы хотим получить такую форму:

Label and textinput.png

В файле index.html нашего модуля пишем:

 <span translate="_">Server name:</span>&nbsp;
 <input type="text" class="text" name="your_server" style="width:120px;"/>

Если строка Server name: определена в файле переводов, то она будет переведена. Ни изменять значение, ни читать его мы больше не будем.

Поле ввода имеет имя your_server, по которому можно обращаться к данному полю. Писать или читать его значение. Для того, чтобы записать значение 127.0.0.1 в это поле, в файле ajax.scm пишем:

 (form-update-value "your_server" "127.0.0.1")

Для того, чтобы прочитать значение из поля, в файле ajax.scm пишем

 (form-value "your_server" )

В более сложном виде для передачи значения в backend по имени backend_name пишем, например, так:

 (catch/message
        (lambda()
        (woo "new" "/backend_name/" 'server (form-value "your_server") 'language (form-value "language"))))

В этом случае в backend передаются параметр server и значение form-value "your_server", а также language и form-value "language" для возможности правильного перевода.

Более удобным является использование

 (form-value-list '("field1" "field2" "field3" "field4")

В этом случае передаются пары значений имя_поля значение_поля

Каким образом мы получим значение нашего параметра в backend, в данной статье рассматриваться не будет. Предположим, что значение мы получили и нам осталось выполнить вызов

 write_string_param param_name param_value

В нашем случае

 write_string_param your_server your.domain.com

Теперь обратимся к backend-у, иначе он нам сам ничего отдавать не будет. В ajax.scm пишем функцию

 (form-update-value "your_server" (woo-read "/backend_name"))

Или более универсальный вариант

 (form-update-value-list (woo-read-first "/backend_name"))

В этом случае имена параметров должны иметь такие же имена, как и имена в формах.

Именованные метки

В рассмотренном выше примере мы не могли изменить надпись возле поля ввода. Если нам такая функциональность нужна, то можно использовать

Разместим в файле index.html такой фрагмент

 <span translate="_">Used base:</span>&nbsp;
 <u><span class="alterator-label" name="base_"/></u>&nbsp;
 <span translate="_">on host</span>&nbsp;
 <u><span class="alterator-label" name="host_"/></u>

В файле ajax.scm создадим функцию

 (define (constr_string)
  (let* ((data (woo-read "/backend_name/string" ))
         (cur_base (and (pair? data) (woo-get-option (car data) 'base)))
         (cur_host (and (pair? data) (woo-get-option (car data) 'host)))
         )
       (form-update-value "base_" cur_base)
       (form-update-value "host_" cur_host) ))

Которая установит нам нужные значения, при условии, что backend вернет нам пары значений.

В результате у нас получилась такая строка

Constructed string.png

Кнопки, радиокнопки и переключатели

Кнопки

Группа радиокнопок (radio) (переключатель с единственным выбором, "ИЛИ")

Чтобы наши радиокнопки переключались, они все должны иметь одинаковое имя. Разместим в форме набор радиокнопок. Все они имеют одинаковое имя (use_src), но разные "value". Рядом с кнопками разместим надписи, для выравнивания используем таблицу (в примере не показано).

 <input type="radio" name="use_src" value="system" checked="#f"/>
 <input type="radio" name="use_src" value="local" checked="#t"/>
 <input type="radio" name="use_src" value="localldap" checked="#f"/>
 <input type="radio" name="use_src" value="remoteldap" checked="#f"/>

Одна из кнопок включена по умолчанию. Это выглядит так:

Radiobutton group.png

Вызов (form-value "use_src") в ajax.scm вернет вам значение той радиокнопки, которая в данный момент выбрана, а (form-update-value "use_src" "system") установит радиокнопку с value="system" в включенное состояние. Нам остается только узнать, какую из радиокнопок включать у backend-а.

 (form-update-value "use_src" (woo-read "/backend" ))

Полезным бывает обработать изменение состояния группы переключателей без обращения к backend-у. Для этого в удобном нам месте напишем

 (form-bind "use_src" "change" set_src)

а в функции set_src - нужные действия.

Группа чекбоксов (checkbox). (Переключатель с множественным выбором "И").

Есть два варианта реализации данного механизма:

  • Таблица класса alterator-checklistbox
  • Набор переключателей, формируемый вручную.

Для создания таблицы в index.html пишем

 <table class="alterator-checklistbox" name="checklistbox"/><br/>

Для заполнения таблицы в файле ajax.scm пишем функцию

 (form-update-enum "checklistbox"
        (woo-list "/backend/checklistbox" 'language (form-value "language")))

Можно для чтения списка передать набор параметров, так же, как и 'language (form-value "language") При этом, в backend результат возвращается при помощи вызова

 write_enum_item "$name" "$label"

Если "$label" не передается, то в качестве значения используется "$name"

После того, как список заполнен, необходимо установить некоторые чекбоксы в состояние "включено".

Для этого используется

 (form-update-value  "checklistbox" '("список_имен_которые_нужно_включить"))

В результате, на экране, мы получим примерно такой набор:

CheckBox group.png

Создание набора, формируемого вручную несколько сложнее, в плане дизайна и размещения элементов в форме. В файле index.html, в таблице, или как будет удобно, размещаем набор переключателей (Как разместить метки рядом с переключателем, надеюсь, понятно.)

 <input type="checkbox" name="local" value="#t"/>
 <input type="checkbox" name="enable_tls" value="#t"/>
 <input type="checkbox" name="local_and_tls" value="#t"/>

Включаем (если нужно) состояние по умолчанию.

В файле ajax.scm определяем функцию

 (define (read_ports)
    (form-update-value-list
      '("local" "enable_tls" "local_and_tls") (woo-read-first "/openldap/config")))

которая установит нам все переключатели в нужное состояние, если backend нам правильно ответит. Правильный ответ backend-а определяется вызовом write_bool_param Например:

  if [ "${url/ldap:\/\/localhost\/[[:space:]]ldaps:\/\/\//}" != "$url" ];then
    write_bool_param 'local_and_tls' 'yes'
    write_bool_param 'local' 'no'
    write_bool_param 'enable_tls' 'no'
  fi

В результате, на экране получится

CheckBox group main.png

Списки

Выпадающий список (select)

Набор значений для выпадающего списка можно задать непосредственно в форме, равно как и получить от backend-а. В случае, если набор значений заранее не определен, то только из backend-а. Разместим в форме такой код:

 <span translate="_">Shell:</span>
 <select name="loginshell"/>

Список пуст. Надпись будет переведена. В файле ajax.scm определим функцию заполнения списка значениями, получаемыми от backend-а.

 (form-update-enum "loginshell" (woo-list "/backend_name/shell"))

В backend-е пишем, к примеру, так:

 #!/bin/sh
 
 po_domain="alterator-test"
 alterator_api_version=1
 
 . alterator-sh-functions
 
 list_shell(){
    write_enum_item "/sbin/nologin"
    while read sh; do
        [ -x "$sh" ] || continue
        write_enum_item "$sh"
    done </etc/shells
 }
 
 on_message() {
  case "$in_action" in
    read)
    ;;
    write)
    ;;
    list)
        case "$in__objects" in
            shell)
                list_shell
            ;;
        esac
    ;;
  esac
 }
 
 message_loop

Проверяем наш backend,

# alterator-cmdline /backend_name/shell action list

name:/sbin/nologin
label:/sbin/nologin

name:/bin/sh
label:/bin/sh

name:/bin/bash
label:/bin/bash

name:/bin/ash
label:/bin/ash

name:/bin/bsh
label:/bin/bsh

Проверяем работу формы. Видим Select.png

Таблицы

Изображения

Для добавления изображения в форму достаточно добавить

 <img class="alterator-img" name="image_name"/>

Каким-либо способом получить путь к файлу изображения относительно каталога /usr/share/alterator/design/images/

и вызвать (form-update-value «image_name» «image_path») Пример использования есть в разделе Изменяющиеся иконки

Динамические формы

Видимость элементов

Предположим, часть элементов формы имеет отношение к некоторому состоянию переключателя. Создадим форму следующего содержания

 <html wf="none">
    <body>
        <form method="POST">
        <input type="checkbox" name="mode" checked="#t"/>&nbsp;
        <b><span translate="_">Show area</span></b>
        <hr/>
        <p>Этот текст будет отображаться постоянно</p>
        <div name="hidden_area" style="display:inline">
            <b>После выключения опции текст в этой области будет скрыт</b>
        </div>
        <p>И этот текст будет отображаться постоянно</p>
        </form>
    </body>
 </html>
</soutce>
При старте формы область"hidden_area" будет видна. Теперь, после переключения режима,
эта область должна скрыться. 
Для этого, в ajax.scm включим обработчик события 
<source lang="html4strict">
 (form-bind "mode" "change" change_mode)

и напишем функцию change_mode

 (define (change_mode)
        (form-update-visibility '("hidden_area") (form-value "mode")))

Чекбокс включен: Din area1.png

Чекбокс выключен: Din area2.png

Естественно, вместо одной строки текста можно скрывать много всяких элементов формы.

Доступность элементов

Изменяющиеся иконки

Наша задача отобразить некоторое состояние системы пикрограммой. Состояние системы можно получить от backend-а или от элементов управления.

Приведем минимальный пример index.html

 <html wf="none">
  <body>
    <form method="POST">
        <input type="radio" name="set_status" value="locked" checked="#t"/>&nbsp;
        <span translate="_">Lock this</span><br/>
        <input type="radio" name="set_status" value="unlocked" checked="#f"/>&nbsp;
        <span translate="_">UnLock this</span><br/>
        <img class="alterator-img" name="status"/>
    </form>
  </body>
 </html>

Изменение состояния радиокнопок должно отобразиться иконкой, но ее src не указан. В файле ajax.scm пишем

 (define-module (ui test ajax)
    :use-module (alterator ajax)
    :use-module (alterator str) ;; Нужно для работы string-append
    :use-module (alterator woo)
    :export (init))
 
 (define (set_status)
    (form-update-value "status" (string-append "test/"
        (car (string-cut-repeated (or (form-value "set_status") "unlocked") #\,))
        ".png")))
 
 (define (init)
    (set_status)
    (form-bind "set_status" "change" set_status)
 )

Функция (string-append "test/" (car (string-cut-repeated (or (form-value "set_status") "unlocked") #\,)) ".png") соберет нам строку вида "test/locked.png" и передаст ее в качестве аргумента для form-update-value

И вот результат Locked.png <--> Unlocked.png

См. также