Sekcja pozwala wstrzykiwać kod do layoutu: arkusze CSS w <head> lub skrypty JS przed </body>. Nie jest wbudowana w silnik handlebars – wprowadzamy ją jako helper w konfiguracji engine.
app.engine('handlebars', expressHandlebars({
defaultLayout: 'main',
extname: '.hbs',
helpers: {
section: function(name, options) {
if(!this._sections) this._sections = {}
this._sections[name] = options.fn(this)
return null
},
},
}))
Zdefiniowanie sekcji w szablonie /views/my_template.handlebars
{{#section 'head'}} <!-- we want Google to ignore this page --> <meta name="robots" content="noindex"> {{/section}} <h1>Test Page</h1> <p>We're testing some script stuff.</p> {{#section 'scripts'}} <script> document.querySelector('body') .insertAdjacentHTML('beforeEnd', '<small>(scripting works!)</small>') </script> {{/section}}
Do layout’u dodajemy sekcje o tych samych nazwach co w widokach (home, scripts)
<head> {{#section 'head'}} <meta name="robots" content="noindex"> {{/section}} </head> <footer>...</footer> {{#section 'scripts'}} <script> const div = document.createElement('div') div.appendChild(document.createTextNode('(scripting works!)')) document.querySelector('body').appendChild(div) </script> {{/section}} </body>
Partials views/partials/weather.handlebars – elementy, widget’y do użycia w wielu szablonach
<div class="weatherWidget"> {{#each partials.weatherContext}} <div class="location"> <h3>{{location.name}}</h3> <a href="{{location.forecastUrl}}"> <img src="{{iconUrl}}" alt="{{weather}}"> {{weather}}, {{temp}} </a> </div> {{/each}} <small>Source: <a href="https://www.weather.gov/documentation/services-webapi"> National Weather Service</a></small> </div>
Kontekst (dane) do widgetu (partials) dostarczamy poprzez midleware korzystajc z obiektu res.locals.partials.partial_name. Poniżej część biblioteki zapisana w pliku /lib/middleware/weather.js
// Dane z sieci, bazy danych - tu z tablicy - dostępne poprzez obietnicę const getWeatherData = () => Promise.resolve([ { location: { name: 'Portland', coordinates: { lat: 45.5154586, lng: -122.6793461 }, }, forecastUrl: 'https://api.weather.gov/gridpoints/PQR/112,103/forecast', iconUrl: 'https://api.weather.gov/icons/land/day/tsra,40?size=medium', weather: 'Chance Showers And Thunderstorms', temp: '59 F', }, { location: { name: 'Bend', coordinates: { lat: 44.0581728, lng: -121.3153096 }, }, forecastUrl: 'https://api.weather.gov/gridpoints/PDT/34,40/forecast', iconUrl: 'https://api.weather.gov/icons/land/day/tsra_sct,50?size=medium', weather: 'Scattered Showers And Thunderstorms', temp: '51 F', }, ... ])
// Pobrane dane przypisane do zmiennej partials.weatherContext poprzez res.locals const weatherMiddleware = async (req, res, next) => { if(!res.locals.partials) res.locals.partials = {} res.locals.partials.weatherContext = await getWeatherData() next() } // Export middleware jako moduł module.exports = weatherMiddleware
W pliku głównym dołączamy middleware
const weatherMiddleware = require('./lib/middleware/weather') .... app.use( weatherMiddleware )
Wywołanie pliku (partials) w widoku (szablonie) np. /views/home.handlebars. Nazwa pliku z widgetem
{{> weather}}