Props
Any content in your app has access to a basic set of information shared between pages and its respective layouts when rendering to generate the final HTML document.
This information is stored in the props
variable.
While part of this information comes directly from the app router (like uri and params) that can be used to retrive information or generate data, other props
can be configured throught magic methods defined in page.js
and layout.js
when needed (like title, icons, metadata, styles and scripts). This information will be used to generate the <head>
tag in th HTML document.
The content
prop is very important to the renderer, it contains the generated HTML from the page to the layouts following the nesting process in a route. See more about nesting.
Using Props
As we saw in rendering, layout.js
and page.js
have a content
function returning the generated HTML part.
This function will always receive all these props:
PROP | TYPE | Description |
---|---|---|
title | string | The Page Title |
icons | object | List of Favicons |
metadata | object | All metadata |
styles | array | List of css files |
scripts | array | List of javascripts files |
content | array | Current rendered content |
params | object | URL params |
uri | string | Current URI |
data | object | Request Data |
So you can use this information to create the content in any way.
For example, if using a dynamic route we can use the dynamic part of the segment in params
prop to create the content.
return { content: (props) => { const article = getArticle(props.params.id); if (!article) { return { redirect: "/not-found" }; } return ` <article> <h1>${article.title}</h1> <div class="summary">${article.summary}</div> <div class="author">${article.author}</div> <div class="published">${article.published}</div> <div class="content">${article.content}</div> </article> `; } }
When using layout.html
and page.html
this props can be accessed by ${props.*}
tokens directly written into the HTML.
return { title: (props) => { return "Dashboard"; } }
... <h1> <a href="${props.uri}"> ${props.title} </a> </h1> ...
Good to know
You can add custom props to extend this functionality in many ways. Learn how to do it in Custom Props section.
Setting Props
To modify the <head>
HTML elements such as <title>
and <meta>
tags Previous.js provides these magic methods.
Method | Return | Description |
---|---|---|
title | string | Sets the page title. |
icons | object | Sets the favicon and other icons. |
styles | array | Add a list of stylesheet files. |
sctipts | array | Add a list of javascript files. |
metadata | object | Sets any other metadata. For example all SEO content like description, author, viewport, etc. |
type | string | Define the content type. |
All these methods can be used in pages and layouts and its props will be updated by the renderer using the nesting from pages to layouts.
This means any prop set in a page can be used in the layout too.
return { title: (props) => { return 'My First Page'; } }
return { title: (props) => { return 'My App :: ' + props.title; } }
In the example above we set the title in page and the layout use this title adding a prefix to it. So the final document title will looks like:
<html> <head> ... <title>My App :: My First Page</title> ... </head> <body> ... </body> </html>
Good to know
Some of these magic methods (like styles and scripts) will append the list sequentially in a determinated order. See more in Styles and Scripts sections.
Title
Any page or layout can manage its title by extending the returning object with the method title
.
return { title: (props) => { return 'My First Page'; }, content: ({ title }) => { return `<h1>${title}</h1>`; } }
Good to know
You should not manually add
<head>
tags such as<title>
and<meta>
to root layouts.
This method will always receive all the page props to process any information before returning the final title.
When using Layouts you can use nesting to generate a composed title:
return { title: (props) => { return 'My App - ' + props.title; } }
The resulting HTML will looks like this:
<html> <head> ... <title>My App - My First Page</title> ... </head> <body> ... <h1>My First Page</h1> ... </body> </html>
Icons
Use this method to add a favicon or other icons to your Web App that appear in places like web browser tabs, phone home screens, and search engine results.
The returning object must have a key with the icon you want to add and a value with the public path to an icon resource in your project or an external URL.
return { icon: (props) => { return { 'icon': '/favicon.ico', 'shortcut icon': '/shortcut-icon.png', 'apple-touch-icon': '/apple-icon.png' }; } }
Remember! Do not forget to put '/' at start of the URL to refer a resource from
public
folder.
The resulting HTML will looks like this:
<html> <head> ... <link rel="icon" href="/favicon.ico" /> <link rel="shortcut icon" href="/shortcut-icon.png" /> <link rel="apple-touch-icon" href="/apple-icon.png" /> ... </head> ... </html>
Good to know
You should not manually add
<link rel="icon" ...>
tag.
Styles
This prop allows you to style your application with CSS.
Use this method to setup a list of stylesheet URLs you want to include in the final document.
return { styles: (props) => { return [ '/vendor/library/custom.css', '/css/main.css', ]; } }
This prop will apend the list of CSS files in inverse order from route hierarchy but maintaining the order in the list.
This means CSS files from root layout will be loaded always before page CSS files.
This allows the web application to load the main dependencies first and in the same order.
Good to know
You should not manually add
<link rel="...">
tag.
Important!
When navigating between pages, Previous.js will autoload stylesheets from diferent pages once. So the loading order will follow the navigation order and all previously loaded stylesheets will remain loaded. Ensure your page styles do not use generic selectors if you want to only work on that page.
Scripts
By default, Previous.js comes with jQuery so you do not need to include this library, but sometimes your app will need some aditional scripts to create an slider, control the UI of your App or add other interactions.
Use this method to create a list of scripts you want to include in the final page.
return { scripts: (props) => { return [ 'https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.21/lodash.min.js', '/vendor/library/custom.js', '/js/app.js', ]; } }
Like the styles
prop, this prop will apend the list of JS files in inverse order from route hierarchy but maintaining the order in the list.
This means JS files from root layout will be loaded always before page JS files.
This allows the web application to load the main dependencies first and in the same order.
Good to know
You should not manually add
<script src="..."></script>
tag.
If you need to run any script after the page is loaded, then you have to use the ready
method.
return { ... ready: () => { console.log('Hello, page loaded!'); // Call other methods... } }
This script will be executed any time you enter the page.
Good to know
Do not use the onload jQuery function
$(function() { ... });
on your scripts. Better use theready
function.
Important!
When navigating between pages, Previous.js will autoload scripts from diferent pages once. So this scripts will only run once.
Metadata
This method provides a way to write any type of Metadata different than described above.
This information could be interesting to powerup SEO descriptions in your Web App.
It must return an object with a key value-pair corresponding with name and content of a <meta>
tag.
Here is an example of some of the porperties you can define with this methor.
return { metadata: (props) => { return { description: "My awesome description", keywords: "Previous.js,jQuery,JavaScript", author: "necro_txilok", viewport: "width=device-width, initial-scale=1", "prop:og:title": "Previous.js" }; } }
Good to know
You should not manually add
<meta name="..." content="...">
tag.
Sometimes we need to add different metadata depending on the page we are navigating, so you can use this method in page.js
to setup with the needed metadata.
If the same property is set in some of the wrapped layouts the page information will have preference over the layouts.
return { metadata: (props) => { return { description: "The Dashboard Page ;)" }; } }
Type
If you need to return a page in a different format than text/html
use this method do change the content-type
header in the returning response.
For example you can create a page in plain text like this:
return { type: 'text/plain', content: (props) => { return 'Hola Mundo!'; } }
Custom Props
Sometimes we need to add custom data to props for using later in content
renderer even in parents layouts.
You can do this by defining the data
method and returning an object with the extra data like this:
return { data: (props) => { return { year: (new Date()).getFullYear() }; } }
So you can use it in the page content:
... <p>Created in ${props.year}.</p> ...
And in layout, for example:
return { metadata: (props) => { return { year: props.year }; } }
Learn more about using custom props in Components or Data sections.