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

Typo3 9.5.8指定文件夹记录分页加载及加载更多实现问询

Hey Michael, let's walk through exactly how to build that "Load more" feature for your TYPO3 9.5.8 custom extension—AJAX doesn't have to feel intimidating, we'll break it into simple, actionable steps.

1. Backend Setup (TYPO3 Extension Logic)

First, we need to handle pagination and AJAX-friendly data fetching in your extension's controller:

  • Create two controller actions:
    • A listAction for the initial page load: This will fetch the first batch of records (e.g., 10) using TYPO3's QueryBuilder. Calculate the total number of records too, and pass both the initial records and total count to your Fluid template.
      Example snippet for listAction:
      public function listAction() {
          $limit = 10;
          $offset = 0;
          
          // Fetch initial records
          $queryBuilder = $this->objectManager->get(QueryBuilder::class);
          $records = $queryBuilder
              ->select('*')
              ->from('tx_yourextension_domain_model_record')
              ->setMaxResults($limit)
              ->setFirstResult($offset)
              ->execute()
              ->fetchAllAssociative();
          
          // Get total record count
          $totalRecords = $queryBuilder
              ->count('uid')
              ->from('tx_yourextension_domain_model_record')
              ->execute()
              ->fetchColumn(0);
          
          $this->view->assignMultiple([
              'records' => $records,
              'totalRecords' => $totalRecords,
              'currentOffset' => $limit,
              'loadLimit' => $limit
          ]);
      }
      
    • A loadMoreAction for AJAX requests: This action will accept offset and limit parameters, fetch the next batch of records, and return only the HTML snippet for those records (no full page layout). Disable the template layout here to avoid wrapping the output with your site's header/footer.
      Example snippet for loadMoreAction:
      public function loadMoreAction(int $offset, int $limit) {
          // Fetch next batch of records
          $queryBuilder = $this->objectManager->get(QueryBuilder::class);
          $records = $queryBuilder
              ->select('*')
              ->from('tx_yourextension_domain_model_record')
              ->setMaxResults($limit)
              ->setFirstResult($offset)
              ->execute()
              ->fetchAllAssociative();
          
          // Render only the record item template (no layout)
          $this->view->setLayoutRootPaths([]);
          $this->view->assign('records', $records);
          return $this->view->render('Record/ItemList');
      }
      
  • Register AJAX route: To let TYPO3 handle the AJAX request, add an entry in your ext_localconf.php to map an eID to your controller action:
    $GLOBALS['TYPO3_CONF_VARS']['FE']['eID_include']['your_extension_loadmore'] = \Vendor\YourExtension\Controller\RecordController::class . '::loadMoreAction';
    
2. Frontend Template (Fluid)

Set up your list template to render initial records and hold the "Load more" UI elements:

  • Render initial records: Create a container for your records, and loop through the initial batch:
    <div id="records-container">
        <f:for each="{records}" as="record">
            <!-- Your record HTML here, e.g.: -->
            <div class="record-item">
                <h3>{record.title}</h3>
                <p>{record.description}</p>
            </div>
        </f:for>
    </div>
    
  • Add Load More UI: Include hidden fields to track state, a loading indicator, the button, and a "no more records" message:
    <input type="hidden" id="current-offset" value="{currentOffset}">
    <input type="hidden" id="total-records" value="{totalRecords}">
    <input type="hidden" id="load-limit" value="{loadLimit}">
    
    <div id="loading-status" style="display: none;">Loading more records...</div>
    <button id="load-more-btn" class="btn btn-primary" {f:if(condition: currentOffset >= totalRecords, then: 'style="display:none;"')}>
        Load more
    </button>
    <div id="no-more-records" style="display: none;">No more records to display.</div>
    
  • Create a partial for record items: Make a Record/ItemList.html partial that only renders the record items (this is what your loadMoreAction will return):
    <f:for each="{records}" as="record">
        <div class="record-item">
            <h3>{record.title}</h3>
            <p>{record.description}</p>
        </div>
    </f:for>
    
3. AJAX Handling (JavaScript)

Add a script to handle the button click, fetch new records, and update the DOM:

document.addEventListener('DOMContentLoaded', function() {
    const loadBtn = document.getElementById('load-more-btn');
    const recordsContainer = document.getElementById('records-container');
    const currentOffsetInput = document.getElementById('current-offset');
    const totalRecordsInput = document.getElementById('total-records');
    const loadLimitInput = document.getElementById('load-limit');
    const loadingStatus = document.getElementById('loading-status');
    const noMoreMsg = document.getElementById('no-more-records');

    loadBtn?.addEventListener('click', function() {
        const currentOffset = parseInt(currentOffsetInput.value);
        const totalRecords = parseInt(totalRecordsInput.value);
        const loadLimit = parseInt(loadLimitInput.value);

        // Exit if all records are loaded
        if (currentOffset >= totalRecords) {
            noMoreMsg.style.display = 'block';
            loadBtn.style.display = 'none';
            return;
        }

        // Disable button and show loading state
        loadBtn.disabled = true;
        loadingStatus.style.display = 'block';

        // Fetch new records via AJAX
        fetch(`/index.php?eID=your_extension_loadmore&offset=${currentOffset}&limit=${loadLimit}`)
            .then(response => {
                if (!response.ok) throw new Error('Request failed');
                return response.text();
            })
            .then(html => {
                // Append new records to the container
                recordsContainer.insertAdjacentHTML('beforeend', html);
                // Update offset
                currentOffsetInput.value = currentOffset + loadLimit;
                // Reset UI state
                loadBtn.disabled = false;
                loadingStatus.style.display = 'none';
                // Hide button if all records are loaded
                if (currentOffset + loadLimit >= totalRecords) {
                    loadBtn.style.display = 'none';
                    noMoreMsg.style.display = 'block';
                }
            })
            .catch(error => {
                console.error('Error loading records:', error);
                loadBtn.disabled = false;
                loadingStatus.style.display = 'none';
            });
    });
});
4. Critical TYPO3-Specific Notes
  • CSRF Protection: For security, add a CSRF token to your AJAX request. In your Fluid template, add <f:form.csrfToken as="csrfToken" />, then include it in the fetch headers:
    fetch(`/index.php?eID=your_extension_loadmore&offset=${currentOffset}&limit=${loadLimit}`, {
        headers: {
            'X-TYPO3-CSRF-Token': '{csrfToken}'
        }
    })
    
  • Template Rendering: Ensure your loadMoreAction doesn't load the full site layout. Using setLayoutRootPaths([]) in the action prevents TYPO3 from wrapping the output with your default layout.
  • Performance: Use QueryBuilder efficiently—only select the fields you need instead of *, and consider caching the total record count if your data doesn't update frequently.

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.14 08:30:15