In website operation, collecting user feedback and inquiries is an important link to improve service quality and understand user needs.AutoCMS (AutoCMS) provides a flexible and powerful message management feature that allows you to easily display the message form on the frontend template and supports custom fields to meet the information collection needs of different business scenarios.

To implement dynamic display of the user submitted comment form and its custom fields in the AnQiCMS template, we mainly use a core tag:guestbookThis tag can retrieve all the comment field information you have configured in the background, and then render it to the front-end page through a loop, thereby building a completely dynamic comment form.

Understandguestbooktags

guestbookThe label is designed by AnQi CMS specifically for comment form, its basic usage is very intuitive:

{% guestbook fields %}
    {# 在这里循环渲染表单字段 #}
{% endguestbook %}

When you use{% guestbook fields %}it will return a variable namedfieldsthisfields变量是一个数组,其中包含了您在安企CMS后台“功能管理”下的“网站留言”中所有配置的表单字段信息,包括系统默认字段和您创建的自定义字段。

In addition, if you are managing multiple sites and want to call the comment form fields of other sites in the current site's template, you cansiteIdParameters to specify the site ID, for example{% guestbook fields with siteId="2" %}.

dynamically render comment form fields

fieldsEach element in the variable represents a form field of a comment form. In the loop traversalfieldsWhen we have an array, we can access each field's detailed properties and use these properties to dynamically generate the corresponding HTML form elements.

Each field object (usually named in loops) will contain the following key attributes:item

  • item.Name: The display name of the field, such as "Your Name", "Phone Number", etc.
  • item.FieldName: Field's internal identifier, used as the HTML form element'snameattributes, for exampleuser_name/contactor the camel case naming form of the field you customize.
  • item.Type: The field type determines which HTML form element should be rendered. Common types include:
    • text: Single-line text input (<input type="text">)
    • number: Numeric input (<input type="number">)
    • textarea:Multi-line text input box (<textarea>)
    • radio:Radio button group (<input type="radio">)
    • checkbox:Checkbox group (<input type="checkbox">)
    • select:Drop-down selection box (<select>)
  • item.Required: Boolean value indicating whether the field is required. If it istrue,we can add in HTML elements.requiredproperties.
  • item.Content: The default value or placeholder text for the field.
  • item.Items: When the field type isradio/checkboxorselectWhen this property is an array, it contains all the available option values. We need to iterate through this array again to generate options.item.ItemsArray to generate options.

General template code for building a comment form.

With these field information, we can build a general template code that can automatically adapt to changes in the backend configuration without manual modification of the frontend HTML.

The following is a detailed example that shows how to dynamically render a comment form in a template, and includes common text, numbers, multi-line text, radio buttons, checkboxes, dropdown selections, and captcha functions:

`twig

{# 隐藏字段,用于指定后端返回格式,例如设置为'html'会返回HTML页面,'json'则返回JSON数据 #}
<input type="hidden" name="return" value="html">

{% guestbook fields %}
    {% for item in fields %}
        <div class="form-group">
            <label for="{{ item.FieldName }}">{{ item.Name }}{% if item.Required %}<span class="required-star">*</span>{% endif %}</label>
            <div>
                {% if item.Type == "text" or item.Type == "number" %}
                    <input type="{{ item.Type }}"
                           id="{{ item.FieldName }}"
                           name="{{ item.FieldName }}"
                           {% if item.Required %}required{% endif %}
                           placeholder="{{ item.Content }}"
                           class="form-control"
                           autocomplete="off">
                {% elif item.Type == "textarea" %}
                    <textarea id="{{ item.FieldName }}"
                              name="{{ item.FieldName }}"
                              {% if item.Required %}required{% endif %}
                              placeholder="{{ item.Content }}"
                              rows="5"
                              class="form-control"></textarea>
                {% elif item.Type == "radio" %}
                    <div class="form-check-group">
                        {% for val in item.Items %}
                            <input type="radio"
                                   id="{{ item.FieldName }}_{{ loop.index }}"
                                   name="{{ item.FieldName }}"
                                   value="{{ val }}"
                                   {% if item.Required %}required{% endif %}
                                   class="form-check-input">
                            <label for="{{ item.FieldName }}_{{ loop.index }}" class="form-check-label">{{ val }}</label>
                        {% endfor %}
                    </div>
                {% elif item.Type == "checkbox" %}
                    <div class="form-check-group">
                        {% for val in item.Items %}
                            <input type="checkbox"
                                   id="{{ item.FieldName }}_{{ loop.index }}"
                                   name="{{ item.FieldName }}[]" {# 多选时name属性需要加[] #}
                                   value="{{ val }}"
                                   class="form-check-input">
                            <label for="{{ item.FieldName }}_{{ loop.index }}" class="form-check-label">{{ val }}</label>
                        {% endfor %}
                        {# 如果需要必填,可以考虑通过JS进行校验,或将Required放在一个隐藏字段中辅助判断 #}
                    </div>
                {% elif item.Type == "select" %}
                    <select id="{{ item.FieldName }}"
                            name="{{ item.FieldName }}"
                            {% if item.Required %}required{% endif %}
                            class="form-control">
                        {% if not item.Required %}<option value="">请选择</option>{% endif %} {# 非必填时提供空选项 #}
                        {% for val in item.Items %}
                            <option value="{{ val }}">{{ val }}</option>
                        {% endfor %}
                    </select>
                {% endif %}
            </div>
        </div>
    {% endfor %}
{% endguestbook %}

{# 验证码部分:如果后台开启了留言验证码功能,这部分代码是必需的 #}
<div class="form-group captcha-group">
    <label for="captcha">验证码<span class="required-star">*</span></label>
    <div class="captcha-input-wrapper">
        <input type="hidden" name="captcha_id" id="captcha_id">
        <input type="text" name="captcha" id="captcha" required placeholder="请填写验证码" class="form-control captcha-input" autocomplete="off">
        <img src="" id="get-captcha" class="captcha-image" alt="验证码" title="点击刷新验证码" style="cursor: pointer;">
    </div>
</div>
<script>
    // JavaScript 用于刷新验证码
    document.getElementById('get-captcha').addEventListener("click", function (e) {
        fetch('/api/captcha')
            .then(response => response.json())
            .then(res => {
                document.getElementById('captcha_id').setAttribute("value", res.data.captcha_id);
                document.getElementById('get-captcha').setAttribute("src", res.data.captcha);
            }).catch(err => console.error("获取验证码失败:", err));
    });
    document.getElementById('get-captcha').click(); // 页面加载时自动获取一次验证码
</script>

<div class="form-group form-actions">
    <button type="submit" class="btn btn-primary">提交留言</button>
    <button type="reset" class="btn btn-secondary">重置</button>
</div>

English