Edit Page

Partials

When using the default view engine (ejs), Sails supports the use of partials (aka "view partials"). Partials are basically just views that are designed to be used from within other views.

They are particularly useful for reusing the same markup between different views, layouts, and even other partials.

<%- partial('./partials/navbar.ejs') %>

Depending on where this render the partial located at views/partials/navbar.ejs, which might look something like this:

<%
/**
 * views/partials/navbar.ejs
 *
 * > Note: This EJS comment won't show up in the HTML served to the browser.
 * > So you can be as verbose as you like.  Just be careful not to inadvertently
 * > type a percent sign followed by a greater-than sign (it'll bust you out of
 * > the EJS block).
 *
 */%>
<div class="navbar">
  <a href="/">Dashboard</a>
  <a href="/inbox">Inbox</a>
</div>

The target path that you pass in as the first argument to partial() should be relative from the view, layout, or partial where you call it. So if you are calling partial() from within a view file located at views/pages/dashboard/user-profile.ejs, and want to load views/partials/widget.ejs then you would use:

<%- partial('../../partials/navbar.ejs') %>

Partials and view locals

Partials automatically inherit the view locals that are available wherever they are used. For example, if you call partial() within a view where a variable named currentUser is available, then currentUser will also be available within the partial:

<%
/**
 * views/partials/navbar.ejs
 *
 * The navbar at the top of the page.
 *
 * @needs {Dictionary} currentUser
 *   @property {Boolean} isLoggedIn
 *   @property {String} username
 */%>
<div class="navbar">
  <div class="links">
    <a href="/">Dashboard</a>
    <a href="/inbox">Inbox</a>
  </div>
  <div class="login-or-signup"><%
  // If the user accessing this page is logged in...
  if (currentUser.isLoggedIn) {
  %><span>
    You are signed in as <a href="/<%= currentUser.username %>"><%= currentUser.username %></a>.
  </span><%
  } 
  // Otherwise the user accessing this page must be a visitor:
  else {
  %><span>
    <a href="/login">Log in</a>
  </span><%
  }
  %>
  </div>
</div>

Overriding locals in a partial

Automatic inheritance of view locals takes care of most use cases for partials. But sometimes, you might want to pass in additional, dynamic data. For example, imagine your app has duplicate copies of the following code in a few different views:

<%
// A list representing the currently-logged in user's inbox.
%><ul class="message-list"><%
  // Display each message, with a button to delete it.
  _.each(messages, function (message) {
  %><li class="inbox-message" data-id="<%= message.id %>">
    <a href="/messages/<%= message.id %>"><%= message.subject %></a>
    <button class="fa fa-trash" is="delete-btn"></button>
  </li><% });
 %></ul>

To refactor this, you might extrapolate the <li> into a partial to avoid duplicating code. But if we do that, we cannot rely on automatic inheritance. Partials only inherit locals that are available to the view, partial, or layout where they're called as a whole, but this <li> relies on a variable called message, which comes from the call to _.each().

Fortunately, Sails also allows you to pass in an optional dictionary (aka plain JavaScript object) of overrides as the second argument to partial():

<%- partial(relPathToPartial, optionalOverrides) %>

These overrides will be accessible in the partial as local variables, where they will take precedence over any automatically inherited locals with the same variable name.

Here's our example from above, refactored to take advantage of this:

<%
// A list representing the currently-logged in user's inbox.
%><ul class="message-list"><%
  // Display each message, with a button to delete it.
  _.each(messages, function (message) { %>
  <%- partial ('../partials/inbox-message.ejs', { message: message }) %>
  <% });
%></ul>

And finally, here is our new partial representing an individual inbox message:

/**
 * views/partials/inbox-message.ejs
 * 
 * An individual inbox message.
 *
 * @needs {Dictionary} message
 *   @property {Number} id
 *   @property {String} subject
 *
 */%>
<li class="inbox-message" data-id="<%= message.id %>">
  <a href="/messages/<%= message.id %>"><%= message.subject %></a>
  <button class="fa fa-trash" is="delete-btn"></button>
</li>

Notes

  • Partials are rendered synchronously, so they will block Sails from serving more requests until they're done loading. It's something to keep in mind while developing your app, especially if you anticipate a large number of connections.
  • Built-in support for partials in Sails is only for the default view engine, ejs. If you decide to customize your Sails install and use a view engine other than ejs, then please be aware that support for partials (sometimes known as "blocks", "includes", etc.) may or may not be included, and that the usage will vary. Refer to the documentation for your view engine of choice for more information on its syntax and conventions.

Is something missing?

If you notice something we've missed or could be improved on, please follow this link and submit a pull request to the sails-docs repo. Once we merge it, the changes will be reflected on the website the next time it is deployed.

Sails logo
  • Home
  • Get started
  • Support
  • Documentation
  • Documentation

For a better experience on sailsjs.com, update your browser.

Documentation

Reference Concepts App structure | Upgrading Contribution guide | Tutorials More

Concepts

  • Assets
    • Default Tasks
    • Disabling Grunt
    • Task Automation
  • Blueprints
    • Blueprint Actions
    • Blueprint Routes
  • Configuration
    • The local.js file
    • Using `.sailsrc` Files
  • Controllers
    • Generating Controllers
    • Routing to Controllers
  • Custom Responses
    • Adding a Custom Response
    • Default Responses
  • Deployment
    • FAQ
    • Hosting
    • Scaling
  • Extending Sails
    • Adapters
      • Available Adapters
      • Custom Adapters
    • Generators
      • Available Generators
      • Custom Generators
    • Hooks
      • Hook Specification
        • .configure()
        • .defaults
        • .initialize()
        • .routes
      • Installable Hooks
      • Project Hooks
      • Using Hooks
  • File Uploads
    • Uploading to GridFS
    • Uploading to S3
  • Globals
    • Disabling Globals
  • Internationalization
    • Locales
    • Translating Dynamic Content
  • Logging
    • Custom log messages
  • Middleware
    • Conventional Defaults
  • Models and ORM
    • Associations
      • Dominance
      • Many-to-Many
      • One Way Association
      • One-to-Many
      • One-to-One
      • Through Associations
    • Attributes
    • Lifecycle callbacks
    • Model Settings
    • Models
    • Query Language
    • Validations
  • Policies
    • Sails + Passport
  • Programmatic Usage
    • Tips and Tricks
  • Realtime
    • Multi-server environments
    • On the client
    • On the server
  • Routes
    • Custom Routes
    • URL Slugs
  • Security
    • Clickjacking
    • Content Security Policy
    • CORS
    • CSRF
    • DDOS
    • P3P
    • Socket Hijacking
    • Strict Transport Security
    • XSS
  • Services
    • Creating a Service
  • Sessions
  • Testing
  • Views
    • Layouts
    • Locals
    • Partials
    • View Engines

Built with Love

The Sails framework is maintained by a web & mobile studio in Austin, TX, with the help of our contributors. We created Sails in 2012 to assist us on Node.js projects. Naturally we open-sourced it. We hope it makes your life a little bit easier!

Sails:
  • What is Sails?
  • Treeline IDE
  • Contribute
  • Logos/artwork
About:
  • The Sails Company
  • Security
  • News
  • Legal
Help:
  • Get started
  • Documentation
  • Docs
  • Enterprise
  • Hire us

© 2012-2018 The Sails Company. 
The Sails framework is free and open-source under the MIT License.