Skip to content

Gravity Forms

Сборка: cd ../../../onepix/wp2lms && … (Turbo core) при необходимости; cd wp2lms-turbo-blocks-mos && npm run build. Корневые npm run build:core|blocks в monorepo отсутствуют.

Vendor block gravityforms/form is remapped to Turbo Twig + shared form controls. GF theme JS/CSS are not loaded on static pages.

  • Requires Gravity Forms plugin (GFAPI).
  • Mapping / inserter / REST register when GF is active (independent of xAPI auth).
  • Opt-in WP learner session: Settings → Turbo → Авторизация ученика по xAPI actor (enable_xapi_actor_session). Without it, entries are guests (created_by = 0).

See also: XAPI_ACTOR_SESSION.md.

  1. Editor: allowlist via BlockMapping; category «Вставки» after Tripetto.
  2. Static render: GFAPI::get_form → FieldTypeRegistry → GravityForm.twig.
  3. Client: deferred gravity-form.js (frontendScripts) → Alpine turboGravityForm.
  4. Submit: POST /wp-json/wp2turbo/v1/gravity-forms/submit → GFAPI::submit_form (primary).
  5. Fallback (when REST transport fails, e.g. local nginx 405): admin-ajax.php?action=heartbeat with nested data[wp2t] → same controller.

Block supports progressAward / progressAmount («Установить прогресс»). On successful submit: data-turbo-progress="gravity-form" → markRootProgressPassed (via window.wp2turboMarkProgress).

Step progress chrome (N/M + bar) is UI-only for multipage forms — not LMS progress.

Page breaks (page fields) become pages[]. UX mirrors Question Bank: badge, track fill, opacity enter animation, focus + live region. Single-page forms hide the chrome.

Standard: text, textarea, number, hidden, html, section, page, select, radio, checkbox, image_choice, multi_choice.

Advanced: email, phone, website, password, name, address, date, time, fileupload, list, multiselect, consent, poll, quiz, survey, likert, rank, rating.

Poll / Quiz honor GF Poll Type / Quiz Type (inputType: radio | select | checkbox) and render the matching choice control.

After submit, when Gravity Forms Polls is active and the form has display results enabled, REST returns structured pollResults (per-field choices with label, ratio, count, selected). Confirmation text keeps the thank-you message only — vendor .gpoll_* HTML is stripped. Alpine renders horizontal CSS bars (.wp2turbo-poll-results), not Chart.js / Mermaid / addon CSS.

Survey honors Survey Field Type (inputType):

Type UI
likert Horizontal scale (labels + radio track); multi-row table when gsurveyLikertEnableMultipleRows
rank Same SortableJS UI as Question Sort (⋮⋮ + ↑↓) → hidden CSV of choice values; needs sortable frontend script
rating Star radios (reversed flips choice order like GF)
radio / checkbox / select / text / textarea Existing choice / text controls

Post: post_title, post_content, post_excerpt, post_tags, post_category, post_image, post_custom_field.

Optional: username when the User Registration addon is present. chainedselect is unsupported in Turbo static (shows fallback UI; hidden when «Скрыть неподдерживаемые поля» is on).

Unsupported (fallback UI): captcha / turnstile / recaptcha / signature / repeater / dropbox / pipe / all pricing & payment types.

Turbo phone fields use the RU mask +7 999 999 99 99 with placeholder +7 999 123 45 67 (example digits, not #). Paste of 8… / 7… / 10-digit national numbers is normalized. GF “standard” (US) validation is relaxed for these values on Turbo submit.

Renders label/description around the shared Gutenberg Separator component (Separator/Separator.twig, wide style).

Choice images come from GF file_url / attachment_id (resolved to a media URL at render).

Modern dropzone: drag-and-drop, remove, reorder (when multipleFiles), client checks for allowed extensions, maxFiles, and maxFileSize (MB → bytes; falls back to WordPress max upload size).

Client-side field visibility mirrors GF Conditional Logic (show / hide, all / any).

Operators: is, isnot, contains, starts_with, ends_with, greater_than, less_than. Checkbox sub-inputs (input_N.M) are supported.

Rule values must match the choice value configured in GF (not only the label text).

Also supported (same rule model):

  • Page skip — page field conditionalLogic → pagesMeta[i].conditionalLogic; hidden pages are skipped by Next/Previous.
  • Next button — nextButton.conditionalLogic / text on the page field → show/hide Next and optional label.
  • Submit button — form.button.conditionalLogic → submitConditionalLogic.

Next / Submit are disabled (like Question Choice) until all visible required controls on the current page are filled (canGoNext / canSubmit).

  • At render: GFCommon::replace_variables_prepopulate via GravityFormsMergeTags for title, description, confirmation HTML, labels, defaults, HTML content, choice text, button labels. Entry-dependent tags (e.g. {quiz_score}) stay unresolved until submit.
  • HTML fields: after merge tags, content runs through GF’s shortcode path ([embed] + do_shortcode), so Gutenberg reusable/pattern shortcodes such as [wp_reusable_render id='1062'] render as normal front-end HTML inside the form. Assets required by those blocks must already be available on the page (or baked into a static compile).
  • After submit: confirmation / merge tags from GFAPI::submit_form (unchanged).

GF Default Value (and selected choices / per-input defaults on Name & Address) are passed as defaultValues into Alpine so x-model does not wipe HTML defaults. Merge tags in defaults are prepopulated at render. Calculation fields ignore static defaults (live formula wins).

Required / format / min–max (Number) / maxLength checks run in the browser as the user types (and on blur). Field messages appear under the control. Maximum Characters shows as a current/max badge (12px) in the control corner. Full GF rules still apply on REST submit.

number fields with enableCalculation + calculationFormula get live Alpine recalculation (GFCalc subset: {…:id} → values, whitelist 0-9 -+/*(), numberFormat decimal_dot/comma). UI shows the result as plain text (hidden input for submit), not an editable control. Pricing fields are not supported. Server still recalculates with GFCommon::calculate on submit.

Settings → Turbo → Скрыть неподдерживаемые поля Gravity Forms (hide_unsupported_gf_fields, default off). When on, gform_field_groups_form_editor / gform_add_field_buttons drop Pricing group and Turbo-unsupported types (captcha, signature, payment, …). Does not change runtime fallback on static pages. Not a Gutenberg allowlist.

  • UI + Conditional Logic run entirely in the browser (OK on cached HTML).
  • Submit tries REST first: POST /wp-json/wp2turbo/v1/gravity-forms/submit (JSON; multipart when files are present).
  • If REST transport fails (typical local nginx 405 / HTML error page), falls back to admin-ajax.php?action=heartbeat with nested data[wp2t] (base64 values). Turbo intercepts heartbeat at priority 0.
  • Static HTML refreshes wp_rest / heartbeat nonces via data[wp2t_boot]=1 before submit (compile-time nonces are user-bound and expire). After a REST transport failure, the page sticks to heartbeat for the rest of the load.
  • restNonce is embedded at render time; long-lived full-page caches may need a fresh nonce strategy.

layoutGridColumnSpan and legacy gf_*_half|third|quarter → .wp2turbo-form__field--w-* in a 12-col grid.

[gravityform id="N"] / [gravityforms id="N"] remapped by GravityFormsContentProcessor.

Окно терминала
npm run build:frontend --prefix ../../../onepix/wp2lms/src/Modules/Turbo
npm run build:core
npm run build:blocks