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

Этот конкретный UX лучше подходит для мелких, простых задач. По мере того, как каждый создаваемый элемент становится все более сложным, тем больше мы хотим предоставить пользователям противоположный опыт, когда они могут перейти на страницу, посвященную созданию или обновлению, не отвлекаясь, чтобы они могли сосредоточить время и усилия только на этом (например, написание сообщение в блоге). А пока давайте сосредоточимся на UX для небольших, простых и быстрых задач (например, управление заметками в блокноте).

Вот краткий набросок того, как выглядит этот пользовательский интерфейс:

UX работает следующим образом:

  1. Заполните данные в форме слева, чтобы создать новый элемент.
  2. После нажатия кнопки «Отправить» элемент добавляется в список справа.
  3. После добавления в список у вас появится новая форма для добавления нового элемента.
  4. Если щелкнуть элемент в списке справа, в форму будут загружены данные для редактирования.
  5. После сохранения изменений элемент в списке справа обновляется.
  6. После обновления форма возвращается в состояние готовности для создания нового элемента.
  7. Вы можете перетаскивать элементы в списке, чтобы изменить их порядок сортировки.

Чтобы упростить работу пользователя, мы должны думать о том, чтобы делать больше в одном пользовательском интерфейсе. Это потребует использования некоторого AJAX. И именно для таких ситуаций мы построили эльдарион-аякс.

В то время как богатая библиотека внешнего интерфейса, такая как React или Vue, может легко создать этот интерфейс, иногда создание и поддержка чего-либо с тяжелым внешним интерфейсом может быть излишним.

Я подготовил демонстрационный проект, чтобы вы могли увидеть, как все это можно довольно просто закодировать с помощью нескольких коротких представлений и небольшого количества javascript, используя eldarion-ajax для выполнения большей части тяжелой работы.

Давайте рассмотрим некоторые основные моменты, начиная со знакомства с eldarion-ajax.

Ajax с разметкой HTML

Верно. Вы можете получить множество функций Ajax, просто обновив разметку и подключив несколько представлений. Не нужно писать javascript.

Во-первых, вы захотите включить eldarion-ajax в свой проект либо добавив его в тег <script>, либо с require('eldarion-ajax') в свой пакет после установки с npm install eldarion-ajax --save.

Как только вы это сделаете, он будет искать теги <form> и <a>, к которым добавлен класс ajax. Если у вас есть <form class="ajax"> или <a href="" class="ajax">, то eldarion-ajax будет подключаться к событиям submit или click и отправлять запросы на сервер, используя метод jQuery $.ajax.

Чтобы контролировать поведение, вы размечаете форму или ссылку различными тегами data. Например, если вы хотите, чтобы Ajax-отправка ссылки использовала POST вместо GET по умолчанию, вы должны:

<a href="url to post to"
   class="ajax"
   data-method="post">
    Post to Server
</a>

Большинство директив о том, что делать с ответом сервера. Они довольно близко сопоставляются с командами манипулирования DOM jQuery.

Например:

<form id="my-form"
      method="post"
      action="url to post to"
      class="ajax"
      data-replace="#my-form">

Возьмет содержимое узла html ответа сервера и заменит элемент <form>.

Вы можете прочитать больше об опциях в eldarion-ajax README.

Демонстрационное приложение

Демонстрационное приложение — это надуманное приложение, разработанное для того, чтобы мы могли сосредоточиться на как, а не на том, что.

Начните работать локально:

pip install -r requirements.txt
npm install
./manage.py migrate
npm run dev

Теперь, когда вы открываете http://localhost:3000, вы можете создать блокнот и добавлять, редактировать и сортировать заметки в этом блокноте. Нет аутентификации, и это, конечно, не производственное приложение.

Шаблоны

С помощью eldarion-ajax мы будем отображать небольшие фрагменты HTML, которые мы называем фрагментами в ответ на различные вызовы Ajax. Это позволяет нам использовать язык шаблонов Django. Это также позволяет нам повторно использовать фрагменты для рендеринга полных страниц, а также для возврата обновленных фрагментов через Ajax.

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

notes.html

Это основной интерфейс, который загружается с сервера целиком как DetailView для объекта Notebook. Представление, как мы вскоре увидим, также включает в себя упорядоченный список заметок для блокнота.

Мы включаем фрагмент формы, _note_form.html, перебираем все существующие заметки и включаем фрагмент _note.html для каждой заметки.

Атрибут data-save-order-url — это то, как мы передаем конечную точку некоторым из наших javascript, чтобы мы могли избежать жестких URL-адресов кодирования. Чуть позже мы узнаем больше о сортировке.

_note_form.html

Форма будет использоваться как для создания, так и для обновления. Вот почему мы передаем переменную post_url, чтобы мы могли контролировать, куда будет публиковаться форма, в зависимости от контекста рендеринга.

Значение data-replace для #note-form означает, что eldarion-ajax заменит всю форму новой, которая представляет собой содержимое, которое мы будем отображать в узле html узла JsonResponse. Мы увидим, как это делается, в разделе ниже, где мы рассмотрим представления.

_note.html

Этот фрагмент довольно прост. Это просто ссылка. Мы стилизуем это как загрузочный .list-group-item.list-group-item-action, но на самом деле это не критично для того, что мы изучаем в этом посте.

data-replace со значением #note-form заменит форму так же, как data-replace формы заменит себя. data-method нет, потому что нам нужно действие по умолчанию GET.

data-id — это уникальный идентификатор этой заметки, необходимый для Sortable, который мы используем для сортировки перетаскиванием и обсудим чуть позже.

Взгляды

NotebookNotesView

Это вид верхнего уровня. Это стандартный DetailView, который загружает объект Notebook на основе первичного ключа в URL-адресе. Здесь нет ничего особенного. Я просто укажу, что note_list загружается из пользовательского свойства Notebook, которое возвращает отсортированный список заметок. Также post_url изначально настроен на создание заметки.

ajax_notes_create

Мы либо добавляем к нашим представлениям ajax префикс ajax_, либо помещаем их в собственный модуль ajax.py. Это не требуется и является просто соглашением. Кроме того, вероятно, мы могли бы сделать некоторую СУШКУ между этими представлениями, если бы использовали представления на основе классов с миксином или двумя.

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

Если форма действительна, мы создаем новый экземпляр формы, в противном случае мы хотим использовать форму с ошибками проверки при отображении _note_form.html.

Есть две вещи, которые мы добавляем к ответу:

Узел html будет использоваться атрибутом data-replace для замены содержимого, найденного при получении его значения и использовании в качестве селектора DOM. В нашем случае это всегда форма #note-form.

Другой узел, append-fragments, — это то, как мы можем отправлять дополнительные данные в браузер для обновления пользовательского интерфейса по мере необходимости. В нашем случае мы хотим добавить новую ссылку на заметку в контейнер #note-list. eldarion-ajax берет элементы из append-fragments, находит элемент DOM с селектором, найденным в ключе, а затем добавляет строку.

Очень похоже на представление создания, здесь мы обрабатываем как GET, так и POST. GET вызывается в ответ на щелчок по ссылке. Мы снова визуализируем форму, но на этот раз мы визуализируем шаблон с контекстом, который включает в себя объект примечания, который мы обновляем, а также post_url, который указывает на это представление для обработки обновления.

Вместо использования append-fragments при обработке POST после действительной формы мы используем fragements. Это заменит примечание в списке, обозначенное $('#note-PK'), содержимым, которое мы отображаем здесь.

Это представление будет обрабатывать обратную публикацию из Sortable, которая будет строкой с конканированными PK, извлеченными из data-id в ссылках. Чуть позже мы увидим, как эти данные используются. Как видите, это очень простое представление, которое не требует особых пояснений.

Javascript

Хотя вам не нужно писать javascript, чтобы использовать Ajax с eldarion-ajax, есть несколько важных моментов, на которые следует обратить внимание, и одна из причин, по которой нам нужно было добавить немного пользовательского javascript.

Прежде всего, вам нужно прочитать файл cookie токена CSRF, и это делается с помощью файла ajaxSendMethod. Я не буду вдаваться в подробности, если вы знаете, что именно здесь мы предоставляем функцию для хука jQuery ajaxSend, который установит заголовок X-CSRFToken, необходимый Django для соответствия проверке CSRF. Если вы этого не сделаете, вы не поймете, почему вы получаете 403 Forbidden ответов.

Одна из причин, по которой мы обсуждаем javascript, заключается в том, что я хотел показать вам, как перезагружать другие виджеты javascript, которые вы можете использовать в своей форме. Здесь у нас есть средство выбора даты, которое загружается при начальной загрузке страницы, но когда вы возвращаете контент в DOM, вам нужно перезагрузить плагин, иначе средство выбора больше не будет прикреплено.

Мы делаем это, перехватывая событие eldarion-ajax:complete, которое отправляется после обработки каждого ответа Ajax. Параметр $el, который передается обработчикам этого события, — это объект, который изначально имел класс ajax и был триггером Ajax-запроса.

Поскольку это событие будет срабатывать для каждого запроса, мы хотим проверить объект $el и посмотреть, нужно ли нам loadDatePicker или нет. Кроме того, пока мы были здесь, я подумал, что было бы полезно активировать активное состояние list-group-item, чтобы оно отображалось как выбранное, пока вы редактируете заметку.

Примечание по заказу

Эта особенность Sortable вообще не связана с eldarion-ajax и полезна для обсуждения в отдельном контексте. Мы видели представление, которое обрабатывает публикацию идентификаторов.

Этот пост исходит из этого Javascript:

Мы получаем saveUrl из того data-save-order-url, что мы видели ранее при обсуждении шаблонов. Мы берем идентификаторы, найденные в data-id, и передаем их объекту sortable, и объединяем для отправки в виде строки на сервер, которую, как вы видели ранее, мы просто сохраняем непосредственно в объекте Notebook.

Мы используем этот список идентификаторов, чтобы указать order_by для свойства Notebook.notes, которое мы отправляем в пользовательский интерфейс, чтобы сохранить порядок ваших заметок.

Мы используем предложения models.Case и models.When для создания оператора SQL, который будет упорядочивать результаты в том же порядке, что и PK для объектов примечания, хранящихся в поле note_order.

Вывод

Надеюсь, мы дали четкое представление о том, как вы можете создать очень полезный опыт для своих пользователей, не погружаясь в богатые интерфейсные библиотеки. В конечном итоге вам может понадобиться перейти на React или Vue, в зависимости от того, насколько больше вы хотите сделать, но когда у вас есть всего несколько видов деятельности, как у нас здесь, мы находим eldarion-ajax, чтобы позволить нам перейти от идеи до запуска, быстрее.

Если у вас есть идея, что вы хотели бы помочь с доставкой, почему бы вам не крикнуть нам. Мы хотели бы поговорить с вами об этом.

Первоначально опубликовано на eldarion.com 6 октября 2017 г.