BEST_PRACTICES /
PJAX

← Back

“We believe the PJAX are the future.” — Whitney Houston

The PJAX library essentially encapsulates the Ajax + pushState + HTML update flow. The native clicks and submits of PJAX-enabled links and forms are hijacked and emulated with Ajax. The end result of such navigation is supposed to be identical to the page refreshing natively.

When to use

PJAX should be used:

Avoid using PJAX for:

Usage

A link is considered to be PJAX-enabled if it's “tagged” with data-pjax attribute and is nested under a container tagged with data-pjax-container attribute, or references a container by ID:

<div id="js-pjax-container" data-pjax-container>
  <nav data-pjax>
    <ol>
      <!-- all of the navigation links will use PJAX -->
      <li><a href="/">Home</a></li>
      <li><a href="/about">About</a></li>
      <li><a href="/faq">FAQ</a></li>
    </ol>
  </nav>

  <!-- this link will use PJAX -->
  <a href="/modern" data-pjax>This will load fast</a>

  <!-- ordinary link will not use PJAX -->
  <a href="/classic">Native page load like it's 1995</a>
</div>

<!-- not nested, but references the PJAX container explicitly -->
<a href="/" data-pjax="#js-pjax-container">The container is over there</a>

A form is considered to be PJAX-enabled if it's tagged with data-pjax attribute directly:

<div id="js-pjax-container" data-pjax-container>
  <form action="/create" data-pjax>
    <!-- form stuff -->
  </form>
</div>

Handling and cancelling the pjax:click event allows us to prevent PJAX behavior on a case-by-case basis. For instance, PJAX is only allowed within the #js-repo-pjax-container element if the link to be followed leads to a resource under the same GitHub repository. Links to any other repository, such as forks, will be followed using native browser behavior.

Server-side

The Rails application is configured to render all PJAX requests using the pjax.html.erb layout by default instead of the more bulky application layout. The pjax? helper is available to distinguish between PJAX requests when it's absolutely necessary.

Whenever any of the assets change on the server, the PJAX responses carry metadata that will force a full refresh on clients that still have the old assets. This is to prevent browsers continuing to load new pages while having stale versions of CSS/JS assets in effect.

If a template needs to set any meta tags specific to the page, it should do so in the content_for :head block and tag the meta items with data-pjax-transient attribute to indicate that they are to be injected in <head> on PJAX load, but removed when we navigate away:

<% content_for :head do %>
  <link rel="alternate" href="<%= request.path %>.patch"
    type="text/plain+patch" data-pjax-transient>
  <meta name="diff-view" content="<%= diff_view %>" data-pjax-transient>
<% end %>