Search code examples
ajaxtypo3fluidtypo3-7.6.xtypo3-extensions

Paginate Widget breaks layout when loaded using ajax in Typo3


There is an issue I am facing in using pagination widget with ajax. What I am doing is, that I select category and then hit an ajax request to fetch the corresponding list by loading the data in the template and returning the html like this:

<f:if condition="{articles}">
<f:then>
    <f:widget.paginate objects="{articles}" as="paginatedArticles" configuration="{itemsPerPage: numberOfRecords}">
        <f:for each="{paginatedArticles}" as="article">
            <h2>
                <f:link.action action="show" arguments="{article : article}"> {article.title}</f:link.action>
            </h2>
            <p>
                <f:format.html>{article.description}</f:format.html>
            </p>
            <hr/>
        </f:for>
    </f:widget.paginate>
</f:then>
<f:else>
    No Records Found
</f:else>

And in my controller in my ajaxMethod I am simply doing

$this->view->assign('articles', $result); so it loads up the template with my result.

But now after rendering the ajax, if I use the pagination, the view breaks. There is no styling or header or anything.

This is how it shows up when I click the next on paginate widget: http://prntscr.com/kr8vg0

Just for completeness, here is the setup.txt which I have written that calls the ajax.

// PAGE object for Ajax call:
tt_content.list.20 = CASE
tt_content.list.20 {
    key.field = list_type
}

ajax = PAGE
ajax {
    typeNum = 1272
    config {
        disableAllHeaderCode = 1
        disablePrefixComment = 1
        additionalHeaders {
            1526302502.header = Content-Type: text/html;charset=utf-8
        }
    }

10 = CONTENT
10 {
    table = tt_content
    select {
          pidInList = this
          orderBy = sorting
          where = (list_type IN ("articleext_list"))
    }
    renderObj = < tt_content.list.20
    }
}

Any help would be appreciated.


Solution

  • The typeNum that drives (should drive) XHR requests from widgets, is added from within the Fluid extension and does not require you to add a special PAGE object.

    Even if you somehow made overrides that call your specific controller action it may not be treated correctly. Usually you would never refer to a content element instance but rather a straight Extbase request bootstrapping. Among other things, because rendering the content object adds wrappers.

    So you should remove this and make sure you pass a QueryResult to the pagination widget. Then override the widget template if necessary. The rest should work without having to configure TS.

    EDIT:

    The pagination widget itself being used in a template that is rendered via XHR means it transfers the arguments you use to load the XHR - including the custom typeNum value. The widget then creates standard links that your click like normal - and they will be a link to the "inner content" of your XHR response because the URL contains a type number.

    Here's where it gets bad: you cannot remove this typeNum once it is added. So you will have to instead cause the next/prev etc. links that are clicked, to cause a new XHR request that loads the content (how you do that very much depends on your JS application so can't guide you there).

    My comment about ensuring a QueryResult is not relevant unless your pages don't change and you for example always see items 1-10.

    But in order to solve this I would actually recommend that you do not use the pagination widget. The main reason being you're already in an XHR context that allows you to receive arguments for your controller action and manipulate the offset and limit parts of the query from within your controller action. That means you can generate your links not to the widget but to the controller action, and for example put a CSS class on the links that should trigger XHR requests vs. those that should reload the entire page (for example to show a detail view). You avoid having to override the pagination template and you control all parameters of all links.

    In fact, I would favor a controller argument for offset above using the pagination widget regardless of XHR or not. There's a long list of technical reasons why that I won't list here but suffice it to say, trading a lot of "black box" for having to create a single argument is a very reasonable and predictable-result thing to do.