Add Page By Form Plugin
The Add Page By Form Plugin is for Grav CMS. It allows users to add a new page by filling in a form.
This plugin uses the possibilities of custom frontmatter. By setting your own variables in the form page frontmatter a priori and optionally letting users override these variable values by filling in corresponding form fields you can transport these data into the new page frontmatter.
The passing on of both the default settings and form field values entered by the end user to the new page frontmatter makes for an extremely configurable solution.
By mixing default settings and configuring the page form you can to a large extent control the appearence and behaviour of the newly added page by using the frontmatter variables present in the new page in a Twig template.
For example, a new page can act as a new blog post simply by setting the appropriate template variable in the form page definition (with the AntiMatter theme, this is
template: item). That template value is inserted in the new page frontmatter and, so, will be used by Grav to display the new page.
Allowing anonymous visitors to create pages is a potential website security risk. It is strongly advised to use the Grav Login Plugin or the Private Grav Plugin to restrict the page creation to logged in users only.
This plugin itself does not provide any security measures. Please take this in consideration before using this plugin.
Installation and Configuration
Typically the plugin should be installed via GPM (Grav Package Manager):
$ bin/gpm install add-page-by-form
Alternatively it can be installed via the Admin Plugin.
Another option is to manualy install the plugin by downloading the plugin as a zip file. Copy the zip file to your
/user/plugins directory, unzip it there and rename the folder to
Here is the default configuration in the configuration file
add-page-by-form.yaml plus an explanation of the settings:
enabled: true date_display_format: 'd-m-Y g:ia' default_title: 'My New Page' default_content: 'No content.' overwrite_mode: false include_username: false auto_taxonomy_types: false use_editor_class: true physical_template_name: true
enableddetermines whether the plugin is active or not;
date_display_formatsets a default date and time format;
default_titlewill be used as a fallback for the new page title when no other value is set;
default_contentwill be used as the page content for the new page when no other value is set;
include_usernamesets whether or not the username of the currently logged in frontend user is included in the new page frontmatter;
overwrite_modedetermines how to act when a page with the same name or slug already exists;
auto_taxonomy_typessaves any new taxonomy types that were input by the user to the site configuration file
use_editor_classdetermines whether or not to change a textarea field into a Markdown editor when the texture field includes the class "editor" (
physical_template_nameshould normally not be used. For more information see the description in the section 'pageconfig' block variables.
Customizing the default configuration
To keep your custom configuration when updating the plugin you need to use a configuration file which is stored in the
Simply edit the plugin options in the Admin panel and the changes will be saved to the configuration file in that location. If you don't use the Admin panel, copy the
add-page-by-form.yaml default file to your
user/config/plugins folder and use that copy to change configuration settings.
Using this plugin requires:
- a normal page containing a Grav Form with a unique name that starts with "add_page";
- optionally, but required for usefulness, one or two blocks of extra page frontmatter variables in that page being:
- a 'pageconfig' block with variables that are used in the new page creation process;
- a 'pagefrontmatter' block with variables that are passed on to the new page frontmatter and can be processed by Twig along the way.
Modifying frontmatter variables
Every frontmatter variable value can be changed by the user when an input field with the same name as the variable is included in the form.
The basic method of modifying is overriding or replacing an initial value. An extreme case of overriding a variable which is quite uncommon but illustrates the process well:
overwrite_modeis set in
- and can be changed in the Plugin configuration in the Admin Panel
- can be set in the
- and finally may be changed again by the end user when the form contains an
Page Headers / Frontmatter
This plugin makes extensive use of Custom Page Headers. Unfortunately the Grav documentation mixes the terms "frontmatter", "page headers" and simply "headers". This may be confusing at first. They all refer to the optional top part of a Grav page which contains data in YAML syntax.
Form page Frontmatter
The frontmatter in the form page and the way it is handled by the plugin is where the flexibility of this plugin originates.
The form page frontmatter is divided into three sections or blocks:
- So called 'root level' variables are intended to act upon the form page itself. They are not passed on to the new page;
pageconfigblock contains variables that are used by the plugin in the new page creation process and do get passed on to the new page frontmatter;
pagefrontmatterblock holds all other variables that must be passed on to the new page frontmatter.
Root level variables
In the examples above the root level configuration options are:
titlesets the title of the page containing the form;
template: formactivates the form on this page (not required when the form page is named
formdefines the form.
From version 2, the use of
parent in the, what is now called, root level block is deprecated. It is however still supported for backwards compatibility.
'pageconfig' block variables
In the optional pageconfig block you can set these, and only these, variables (other variables will be ignored):
parentsets the parent page for the new page. This variable may be an absolute route (for example
parent: /user_contributions) or a relative route (e.g.
parent: articles. In case of an absolute route this route starts from the pages root. A relative route is regarded to start from the form page, so the new page will be a child page of the form page. The form page is also used as the parent page when the set parent page does not exist;
subroutedefines a route from the (initial) parent value. If one or more folders in the route do not exist they will be created;
slug_fieldtells the plugin what field to use as the new page's slug or folder name. When
slug_fieldis missing the plugin tries to use the value of
false) tells the plugin what to do when a page with the same name already exists. With
overwrite_mode: truethe existing page is overwritten. Any additional (media) files besides the page itself which are stored in the existing page folder are deleted as well. With
overwite_mode: falsethe new page slug gets a sequential number attached at the end (for example "my-new-page-1" in case "my-new-page" exists).
overwite_mode: editallows for the page being saved to it's existing folder respecting any already present uploaded files;
false) determines whether or not to include the username of a logged in frontend user in the new page frontmatter;
true) does or does not cause the plugin to use the template name of the new page as that new page's filesystem filename. Defaults to "default" when no template is set in the 'pagefrontmatter' block. When set to
trueto avoid future confusion the frontmatter variable
templateis removed from the new page frontmatter.
A note on parent and subroute
Together the variables
subroute define the new page's destination. Or, in other words, together they set the path or route of the new page filesystem folder in the page structure.
The difference between parent and subroute worded in another way:
- Parent: works on a page level; when there is no page at the parent route, the form page is used as the parent;
- Subroute: works on a folder level; a subroute may consist of empty folders and if a folder in the subroute does not exist it gets created.
'pagefrontmatter' block variables
The content of the optional
pagefrontmatter block will be included in the new page frontmatter.
The form page needs to use a simple single form.
Two examples are included at the end of this ReadMe file.
Mandatory fields and values
It is always a good thing to give each form a unique name, especially when multiple forms are used.
To pre fill form fields with default values the Form name must include the string "add_page". Valid names are for example
Custom Form processing ( Important ! )
To let the plugin process the form after a Submit a custom process action must be set like so:
process: - add_page: true
Redirect to the new page
To show the new page to the user set the
redirect action to the custom value
redirect: '@self' the page will be shown as a regular web page, for example:
process: - add_page: true - redirect: '@self'
To open the new page in the Admin panel use
Note that this plugin does not handle the admin user authentication. If the Admin plugin is not installed or is inactive redirection occurs as if
@self was used.
@self-adminis a very convenient way to learn how to use this plugin as it is easy to view and examine the source of the resulting new page including it's frontmatter in the Admin panel.
Using a Markdown editor in textarea fields
textarea field is given the class
editor it will use the SimpleMDE Markdown Editor.
The variables which are defined and given a value in the
pagefrontmatter blocks may be 'overridden' or in other words replaced by form input fields. In that respect these variables can be seen to hold a set of default values.
There is only one exception to the default variable override behaviour and that is the handling of
taxonomy types. Extra taxonomy types and values (for example tags) which are entered via form fields are added to the new page taxonomy.
To override a default value by user input is simply a matter of including a form field by the same name in the page form.
For example in the example 2 - create a new blog post, the default title is set to "My new Blog post". The form contains a form field of type text with
name: title. Thus the user is prompted to enter a title for the new page in the form but does not need to do so because filling in the title field is not mandatory. If the user enters a title that value is used as the title for the new page. If he or she does not, the default title "My new Blog post" will be used.
Setting taxonomy categories and tags
The Add Blog Post example shows how to let the user add extra tags via the form. Extra categories may be added in the same way.
Handling extra taxonomy types
By default Grav 'knows' two taxonomy types,
tag. Extra taxonomy types may be defined and added just like with any other variables you can include a form field. The new type is then added to the list of taxonomy types instead of replacing the existing types.
This can be done in the
pagefrontmatter block. For example, to define a new taxonomy type named 'department':
pagefrontmatter: taxonomy: - department
And/or in the form:
form: name: my_form fields: - name: taxonomy label: Taxonomy type type: text
This is a feature which calls for a solid look-before-you-leap approach because of it's side effects. Using a new taxonomy type requires it to be included in the list of known taxonomy types. This list is in the site configuration file
By setting the plugin configuration option
auto_taxonomy_types: true new types get automatically saved and can then be used in a collection.
The side effect and possibly downside is that every modification of the site configuration file causes Grav to rebuild the cache, so this may not be desirable with larger sites.
Use with caution!
The least error prone way to test and play with the examples is to set up a fresh Grav site and using it's default theme Antimatter.
Form page example 1: create a normal page
The goal of this example is to show how to let a user create a new page where uploaded images and files are saved along the page (in the same folder). After the user clicked Submit he or she will be shown the new page.
Suppose this minimal Grav website structure in
03.submit-assignment/ default.md 04.assignments/ cmpt363-e100/ default.md drafts/ modular.md reviewed/ modular.md
BTW both modular pages are not required but are mentioned as they could be used to display a collection of draft and reviewed assignments.
Then the 'Submit assignment for review' page (with slug
submit-assignment) full content (both frontmatter and content) could look like:
--- routable: true title: 'Submit assignment for review' template: form visible: true pageconfig: parent: /submitted-assignments/cmpt363-e100/drafts pagefrontmatter: visible: true status: draft template: default course: assignment: 'CMPT363 E100' instructor: name: 'Jane Doe' form: name: addpage-assignment-cmpt363-e100 fields: - name: name label: Name type: text validate: required: true - name: title label: Title type: text validate: required: true - name: content label: 'Assignment text' type: textarea size: long classes: editor validate: required: true - name: attachments label: 'Attachment (PDF only)' type: file multiple: true accept: - application/pdf validate: required: false - name: honeypot type: honeypot buttons: - type: submit value: Submit process: - addpage: null - redirect: '@self' --- Please write your assignment and attach any images and/or files.
Supposing the user has not changed the pre filled title field, has entered his name "Paul Walker", has entered a simple "q.e.d." as the assignment content and uploaded one PDF document, then the full new page will be:
--- visible: true status: draft course: assignment: 'CMPT363 E100' instructor: name: 'Jane Doe' name: 'Paul Walker' title: 'CMPT363 E100' attachments: /Users/rwgc/devroot/repos/grav-test/htdocs/user/pages/assignments/cmpt363-e100/drafts/cmpt363-e100-1/scrum-guide-sept-2013.pdf name: scrum-guide-sept-2013.pdf type: application/pdf size: 273 KB path: /Users/rwgc/devroot/repos/grav-test/htdocs/user/pages/assignments/cmpt363-e100/drafts/cmpt363-e100-1/scrum-guide-sept-2013.pdf --- q.e.d.
On the file system level the file structure will be:
01.home/ default.md 02.add-new-article/ default.md 03.assignments/ cmpt363-e100/ default.md drafts/ cmpt363-e100-1/ default.md scrum-guide-sept-2013.pdf modular.md reviewed/ modular.md
Form page example 2: create a blog post
In this example the user can add a blog post. To ensure the new page will be treated as a blog post simply set the
template variable to be used by the new page to
item. BTW the active theme must include the corresponding template
item.html.twig. This is why it is best to start with Grav's default theme Antimatter.
--- title: 'Add Blog Post' template: form pageconfig: parent: '/blog' include_username: true overwrite_mode: true pagefrontmatter: template: item title: My new Blog post taxonomy: category: blog tag: [journal, guest] form: name: add_page.blogpost fields: - name: author label: 'Author' type: text - name: title label: 'Post Title' type: text - name: taxonomy.tag label: 'Tags (comma separated)' type: text - name: content label: 'Post Content' type: textarea size: long classes: editor - name: images label: 'Images to upload' type: file multiple: true accept: - 'image/*' - name: honeypot type: honeypot buttons: - type: submit value: Submit process: - add_page: true - redirect: '/blog' --- ## New Blog Post Write your blog post:
After the form has been submitted the user is taken to the blog main page where the new post should show up.
Grav Form issue
The form on the form page is a standard Grav form. Please note that the Grav Form Plugin currently (latest test using version 4.0.1) has an issue which prevents the form to be submitted when a form field of type
file is set to
required: true(see issue #106).