SFRA Controllers

SFRA controllers in JetBrains IDEs - typed req and res, middleware navigation, append and replace of base routes, view data and picked templates

An SFRA route is a name, a chain of middleware and a template, joined at run time by server.js. Intellij SFCC joins them in the editor: req and res are typed in every callback, middleware opens in SFRA's modules, an append finds the route it extends, and the template a route renders gets its model as pdict

In an SFRA route, req and res complete with their types, so req.currentCustomer.profile and res.render come up as you type. Cmd+Click on server.middleware.https opens the function in your project's modules/server/middleware.js

Before you start

NeedsWhy
SFRA's modules folder marked as Modules (Global Modules) Rootrequire('server') loads it, see B2C modules and global modules
A valid license or trialRoute and template completion, navigation, gutter icons and Code Vision are paid features, see Purchase & License

Typed req and res

Every function passed to server.get, server.post, server.use, server.append, server.prepend and server.replace gets SFRA's types, with no JSDoc:

ParameterTypeMembers you use most
reqsfra.Requestquerystring, httpParameterMap, form, currentCustomer with profile, addressBook, wallet and raw, locale, session, geolocation, pageMetaData
ressfra.Responserender, json, setViewData, getViewData, redirect, setStatusCode, cacheExpiration, setHttpHeader, print
nextsfra.NextCall it to run the next step
app_custom/cartridge/controllers/Loyalty.js
server.get('Show', server.middleware.https, function (req, res, next) {
    var profile = req.currentCustomer.profile; // sfra.Profile
    this.on('route:BeforeComplete', function (req, res) {
        res.setViewData({ updated: true }); // typed here too
    });
    res.render('account/loyalty', { points: loyaltyHelpers.getPoints(profile.customerNo) });
    next();
});

Inside a route function, this.on takes the route events route:Start, route:Redirect, route:Step, route:BeforeComplete and route:Complete, and types the req and res of its callback

server and middleware

CodeCmd+Click opensCompletes
require('server')SFRA's modules/server.js
server.get, server.post, server.use, server.replaceThe method in modules/server/server.jsget, post, use, replace, middleware, forms, querystring and the other members your SFRA copy defines
server.middleware.httpsThe https function in modules/server/middleware.jshttps, http, get, post, include and any middleware your copy adds
server.forms, server.querystringThe assignment in modules/server.js

Members your SFRA copy doesn't define, such as server.getRoute, open the bundled typings. Middleware of your own cartridges, such as csrfProtection.generateToken or userLoggedIn.validateLoggedIn, comes in through require like any module, see Module Resolution

Extend a route

server.extend(module.superModule) makes a controller an override of the same controller further right on the cartridge path. Then:

CodeWhat happens
server.append(''), server.prepend(''), server.replace('')Completes the routes of the controller you extend, each with its cartridge
Cmd+Click on 'Show' in an append or prependOpens the route it extends, in the nearest cartridge further right on the site's cartridge path
Cmd+Click on 'Show' in server.get('Show', ...)Lists every other definition, append, prepend and replace of the route
The lenses above a routeappend (1), prepend (2) or replace (1) list the cartridges that extend it, see SFRA extensions

To find a route from anywhere, use the B2C Entry Points tab of Search Everywhere. For URLUtils.url('Cart-Show') and other route strings, see Routes and controllers

View data in templates

res.setViewData({ loyaltyPoints: points }) in an append adds pdict.loyaltyPoints to the template the base route renders, in its own cartridge or any other. So does viewData.loyaltyPoints = points on the object res.getViewData() returns. The plugin reads both across the route's handlers, every server.append and server.prepend of it and its middleware, up to 50 functions deep, so csrfProtection.generateToken adds pdict.csrf

In the template, pdict. completes the member with its type, and quick documentation (F1, Ctrl+Q) names the line that sets it. A middleware or helper the plugin can't follow, such as decorate(req, res), keeps the members it knows and stops the unknown member warning, see Render calls

Picked templates

A route that picks its template at run time keeps every link of a literal path:

app_custom/cartridge/controllers/Account.js
var template = req.querystring.panel ? 'account/dashboardPanel' : 'account/accountDashboard';
res.render(template, { account: accountHelpers.getAccountModel(req) });
FormExample
A variable, also one set in if and elsevar view = 'a/mobile', then res.render(view, model)
?:res.render(isGuest ? 'checkout/guest' : 'checkout/login', model)
|| and ??res.render(req.querystring.view || 'search/searchResults', model)

Each path completes template paths, gets the Navigate to template gutter icon , opens with Cmd+Click and is found and renamed with its template. The model joins the pdict of each template. With copies in several cartridges the icon reads Navigate to template (2 cartridges) and opens Choose Template, in the order the server tries them, see Gutter icons

A path built from parts, such as 'account/' + name, or passed in as a function parameter, isn't followed

Troubleshooting

SymptomWhat to do
req. or res. lists nothing in a routeMark SFRA's modules folder as Modules (Global Modules) Root and check the license, see Before you start
server.append('') lists nothingAdd server.extend(module.superModule) and check that another linked cartridge has a controller with the same name
An append opens no base routeThe base controller is in a cartridge that isn't linked, or has another file name
A pdict member from an append is missing in the templateSet it with res.setViewData({...}) or on the object res.getViewData() returns, in the route's own handler, an append or a middleware
A picked template has no gutter iconThe path is built from parts or passed in, see Picked templates

On this page