You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何实现表单自定义显示指定数量的字段?

Solution for Adding "Show X Columns" Pagination to Your CSV Configuration Form

Since DataTables is designed for tables and not dynamic form elements, we can implement a simple client-side pagination system using Bootstrap and vanilla JavaScript. This will let users control how many column configuration groups are visible at once, while preserving all form data for submission.

Step 1: Add Pagination Controls to Your Form

First, add a dropdown for selecting items per page and navigation buttons at the top of your form. We'll also include a page indicator for clarity:

<div class="mb-4">
  <div class="d-flex flex-wrap align-items-center justify-content-between gap-3">
    <!-- Items per page selector -->
    <div class="d-flex align-items-center">
      <label for="itemsPerPage" class="form-label me-2">Show columns per page:</label>
      <select id="itemsPerPage" class="form-select form-select-sm w-auto">
        <option value="10">10</option>
        <option value="25" selected>25</option>
        <option value="50">50</option>
        <option value="all">All</option>
      </select>
    </div>

    <!-- Page indicator -->
    <div class="text-muted">
      <span id="pageIndicator">Page 1 of 1</span>
    </div>

    <!-- Navigation buttons -->
    <div>
      <button id="prevPage" class="btn btn-sm btn-secondary me-2" disabled>Previous</button>
      <button id="nextPage" class="btn btn-sm btn-secondary">Next</button>
    </div>
  </div>
</div>

Step 2: Modify Your Jinja2 Form Loop

Update your form group generation to add a consistent class (column-form-group) and track the index of each column. We'll use Bootstrap cards for each column's controls to improve readability:

<div class="row g-4">
  {% for column in csv_columns %}
    <div class="col-md-4 column-form-group" data-index="{{ loop.index0 }}">
      <div class="card h-100">
        <div class="card-header">
          <h6 class="mb-0">Column {{ loop.index }}</h6>
        </div>
        <div class="card-body">
          <!-- Column name input -->
          <div class="mb-3">
            <label for="col-name-{{ loop.index0 }}" class="form-label">Column Name</label>
            <input 
              type="text" 
              class="form-control" 
              id="col-name-{{ loop.index0 }}" 
              name="col_names[]" 
              value="{{ column.name }}"
              required
            >
          </div>

          <!-- Column type selector -->
          <div class="mb-3">
            <label for="col-type-{{ loop.index0 }}" class="form-label">Column Type</label>
            <select 
              class="form-select" 
              id="col-type-{{ loop.index0 }}" 
              name="col_types[]"
              required
            >
              <option value="string" {% if column.type == 'string' %}selected{% endif %}>String</option>
              <option value="number" {% if column.type == 'number' %}selected{% endif %}>Number</option>
              <option value="date" {% if column.type == 'date' %}selected{% endif %}>Date</option>
              <!-- Add your custom types here -->
            </select>
          </div>
        </div>
      </div>
    </div>
  {% endfor %}
</div>

Step 3: Add JavaScript for Pagination Logic

This script will handle showing/hiding form groups, updating navigation buttons, and responding to user selections. It preserves all form data (even hidden fields are submitted with the form):

document.addEventListener('DOMContentLoaded', function() {
  // Get DOM elements
  const formGroups = document.querySelectorAll('.column-form-group');
  const itemsPerPageSelect = document.getElementById('itemsPerPage');
  const prevBtn = document.getElementById('prevPage');
  const nextBtn = document.getElementById('nextPage');
  const pageIndicator = document.getElementById('pageIndicator');

  // Pagination state
  let currentPage = 1;
  let itemsPerPage = parseInt(itemsPerPageSelect.value);
  const totalItems = formGroups.length;
  let totalPages = itemsPerPage === 'all' ? 1 : Math.ceil(totalItems / itemsPerPage);

  // Update visible form groups and UI state
  function updatePagination() {
    if (itemsPerPage === 'all') {
      // Show all groups
      formGroups.forEach(group => group.classList.remove('d-none'));
      prevBtn.disabled = true;
      nextBtn.disabled = true;
      pageIndicator.textContent = `Page 1 of 1`;
      return;
    }

    // Calculate range for current page
    const startIndex = (currentPage - 1) * itemsPerPage;
    const endIndex = startIndex + itemsPerPage;

    // Show/hide groups based on current page
    formGroups.forEach((group, index) => {
      if (index >= startIndex && index < endIndex) {
        group.classList.remove('d-none');
      } else {
        group.classList.add('d-none');
      }
    });

    // Update button states and page indicator
    prevBtn.disabled = currentPage === 1;
    nextBtn.disabled = currentPage === totalPages;
    pageIndicator.textContent = `Page ${currentPage} of ${totalPages}`;
  }

  // Initial setup
  updatePagination();

  // Handle items per page selection change
  itemsPerPageSelect.addEventListener('change', function() {
    itemsPerPage = this.value === 'all' ? 'all' : parseInt(this.value);
    currentPage = 1; // Reset to first page
    totalPages = itemsPerPage === 'all' ? 1 : Math.ceil(totalItems / itemsPerPage);
    updatePagination();
  });

  // Handle previous page click
  prevBtn.addEventListener('click', function() {
    if (currentPage > 1) {
      currentPage--;
      updatePagination();
    }
  });

  // Handle next page click
  nextBtn.addEventListener('click', function() {
    if (currentPage < totalPages) {
      currentPage++;
      updatePagination();
    }
  });
});

Key Notes:

  • Preserves Form Data: Hidden form groups are still present in the DOM, so all col_names[] and col_types[] values will be submitted when the form is sent to the server.
  • Bootstrap Consistency: Uses Bootstrap's utility classes (d-none) and components (cards, selects, buttons) for a cohesive look.
  • Responsive: The control bar wraps on smaller screens to maintain usability.
  • No External Libraries: Uses vanilla JavaScript so you don't need to add extra dependencies like DataTables.

This implementation gives users full control over how many columns they see at once, making it easier to manage large CSV files without overwhelming the page.

内容的提问来源于stack exchange,提问作者gkuhu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.27 09:29:19