The Product Questions Component renders a list of questions for a product. It is typically used on product detail pages, but it can also power recent‑questions widgets, sidebar lists, or threaded question sections.

Activate the component by adding:

data-v-component-questions

The component supports filtering, sorting, pagination, and nested replies.


Component Options

Options are added as HTML attributes using the data-v-* syntax.

Pagination & Sorting

Option Attribute Description Default
start data-v-start Starting offset for pagination 0
limit data-v-limit Number of questions to display 10
order data-v-order Sort direction for threaded questions (asc, desc) asc

Filtering

Option Attribute Description Default
status data-v-status Question status: 1 = published, 0 = pending, 2 = spam, 3 = trash 1
product_id data-v-product_id Filter by product ID null
slug data-v-slug Filter by product slug null

Additional Options

Option Attribute Description Default
product_title data-v-product_title Include product title (useful for recent‑questions widgets) false

Component Properties

Each question is wrapped in:

data-v-question

The following fields are available inside each question element.

Author Information

Property Attribute Description
username data-v-question-username Username of the questioner
email data-v-question-email Email address
first_name data-v-question-first_name First name
last_name data-v-question-last_name Last name
display_name data-v-question-display_name Display name
author data-v-question-author Full author name
avatar data-v-question-avatar Avatar filename
avatar_url data-v-question-avatar_url Full avatar URL
bio data-v-question-bio Author biography
subscribe data-v-question-subscribe Whether the user subscribed to replies

Question Metadata

Property Attribute Description
question_id data-v-question-question_id Unique question ID
product_id data-v-question-product_id ID of the product the question belongs to
user_id data-v-question-user_id ID of the user who producted the question
url data-v-question-url Author’s website URL
ip data-v-question-ip IP address (if stored)
status data-v-question-status Question status
votes data-v-question-votes Upvotes/downvotes
type data-v-question-type Question type (empty for standard questions)
parent_id data-v-question-parent_id Parent question ID (for threaded replies)
level data-v-question-level Nesting level for threaded questions
created_at data-v-question-created_at Creation timestamp
updated_at data-v-question-updated_at Last update timestamp

Question Content

Property Attribute Description
content data-v-question-content Question text

Product Information (Optional)

Displayed only when data-v-product_title="true" is used.

Property Attribute Description
name data-v-question-name Title of the product the question belongs to
slug data-v-question-slug Slug of the product the question belongs to

HTML Example

<div data-v-component-questions data-v-product_id="url">

  <ol data-v-if="count > 0">

    <li data-v-question>

      <div class="question-wrap">

        <figure class="author-avatar me-2">
          <img data-v-question-avatar_url
               alt="user"
               width="60"
               loading="lazy"
               src="/media/vvveb.svg" 
               data-v-if="question.avatar_url">
        </figure>

        <div class="question-author">

          <a rel="external nofollow ugc" data-v-if="question.url">
            <span data-v-question-author>John Doe<</span>
          </a>


	<div class="question-meta">
	  <span data-v-question-created_at data-filter-friendly_date>3 year ago</span>
	</div>


        </div>

      </div>

		<div data-v-question-content>This is an approved question.</div>

      <div class="reply">
        <a href="#question-form"
           class="reply-btn"
           data-v-vvveb-action="replyTo"
           data-question_id
           data-question_author>
          Reply <i class="la la-reply"></i>
        </a>
      </div>

    </li>

  </ol>

  <div class="alert" role="alert" data-v-if-not="this.default_question_status">
    <div data-v-notification-text>
      <span>Questions are closed</span>
    </div>
  </div>

This example displays a threaded question list with avatars, author names, timestamps, content, and reply actions.

Product Question Form Component

The Question Form handles question submission on product pages. It works together with the Product Questions Component, allowing users to submit new questions or reply to existing ones. The form supports logged‑in users, anonymous questioners (if enabled), CSRF protection, and threaded replies.

To use javascript to product the question without refreshing the page add the following attributes:

data-v-vvveb-action="addQuestion"
data-v-vvveb-on="submit"

These attributes instruct Vvveb CMS to process the form submission through javascript fetch.


How the Question Form Works

The form products data to the current page and is intercepted by the Vvveb action handler. The handler:

  • Validates required fields
  • Checks CSRF token
  • Determines whether the user is logged in or anonymous
  • Creates a new question in the database
  • Assigns the question to the correct product
  • Handles threaded replies via parent_id
  • Returns success or error notifications

If questions require moderation, the submitted question may be stored with status = 0 (pending).


Form Fields

The form includes a mix of visible and hidden fields. These fields are required for proper question submission.

Hidden System Fields

Field Purpose
product_id Identifies the product the question belongs to
slug Product slug (used for redirects and validation)
parent_id ID of the parent question (0 for top‑level questions)
csrf CSRF token for security
firstname-empty Honeypot anti‑spam field (must remain empty)
subject-empty Honeypot anti‑spam field
lastname-empty Honeypot anti‑spam field

Honeypot fields help block bots without affecting real users.


User Identity Fields

These fields are shown only when the user is not logged in:

Field Required Description
author Yes Name of the questioner
email Yes Email address of the questioner

When the user is logged in, these fields are omitted because the system already knows the user’s identity.


Question Content

Field Required Description
content Yes The actual question text

This is the main body of the question.


Replying to Questions

The reply links in the question list use:

data-v-vvveb-action="replyTo"

This action:

  • Scrolls to the question form
  • Sets the hidden parent_id field to the ID of the question being replied to
  • Optionally displays the name of the user being replied to

This enables threaded/nested questions.


Anonymous Questions

The form includes:

data-v-if="this.global.user_id || this.anonymous_questions"

This means:

  • If the user is logged in → show the form
  • If the user is not logged in but anonymous questions are allowed → show the form
  • Otherwise → hide the form

Anonymous question settings are controlled in the site configuration.


Validation & Security

The question form includes several built‑in protections:

  • CSRF token (data-v-csrf)
  • Honeypot fields (firstname-empty, subject-empty, lastname-empty)
  • Server‑side validation of required fields
  • Status filtering (pending, spam, trash)

If moderation is enabled, questions may not appear immediately.


HTML Example

<form id="question-form"
      method="post"
      action=""
      data-v-vvveb-action="addQuestion"
      data-v-vvveb-on="submit"
      data-v-if="this.global.user_id || this.anonymous_questions">

  <input type="hidden" name="product_id" data-v-product-product_id>
  <input type="hidden" name="slug" data-v-product-slug>
  <input type="hidden" name="parent_id" value="0">
  <input type="hidden" name="csrf" data-v-csrf>

  <!-- Honeypot anti-spam fields -->
  <input type="hidden" name="firstname-empty">
  <input type="text" class="visually-hidden" name="lastname-empty" tabindex="-1">
  <input type="text" class="d-none" name="subject-empty">

  <!-- Anonymous user fields -->
  <div data-v-if-not="this.global.user_id">
    <div class="mb-3">
      <label class="form-label">Name</label>
      <input type="text" name="author" class="form-control" required>
    </div>

    <div class="mb-3">
      <label class="form-label">Email address</label>
      <input type="email" name="email" class="form-control" required>
    </div>
  </div>

  <!-- Question text -->
  <div class="mb-3">
    <textarea name="content" rows="5" class="form-control" placeholder="Question" required></textarea>
  </div>

  <!-- Submit -->
  <button type="submit" class="btn btn-primary btn-submit">
    <span class="loading d-none">
      <span class="spinner-border spinner-border-sm"></span>
      <span>Producting...</span>
    </span>

    <span class="button-text">
      <span>Product question</span>
      <i class="la la-long-arrow-alt-right ms-1"></i>
    </span>
  </button>

</form>

This example includes all required fields, anonymous user handling, CSRF protection, and reply support.