#Components
Your Addon can provide Components to the site. The user can disable these Components if they choose which prevents their Build Script from running and allows them to make their own Components with the same name.
#Component Schema
{
// uneditable properties
_id: '63a0db9dd37c3735b468e1f8',
parentVersionId: '63a0458bee56d369bd5c79a6',
managedByAddonId: '639b8f837f5fb8a39404280a',
updatedAt: 1671486365027,
createdAt: 1671486531695,
// basic properties
name: '',
description: '',
type: 'static',
richTextType: '',
isEnabled: true,
// body properties
lang: 'pug',
body: '',
// style properties
styleLang: 'stylus',
style: '',
// fields
fields: [],
fieldGroups: [],
displayField: '',
// tags
tags: [],
// scripts
script: '',
dataScript: '',
buildScript: '',
// seo
seoLang: '',
seoBody: '',
// help
help: [],
}
#Uneditable Properties
Name | Description |
---|---|
_id | Assigned by MercuryCMS when the Component is created |
parentVersionId | Used by MercuryCMS to manage revision history |
managedByAddonId | All of your created Components have this automatically added so they can be removed when the Addon is uninstalled |
createdAt | JavaScript Date the Component was created |
updatedAt | JavaScript Date the Component was last modified |
#Basic Properties
Name | Description |
---|---|
name | The Component's name that determines the HTML tag used to insert it. Use something that won't conflict with Components the user has created |
description | Optional, but you should always provide a description of what the Component does |
type | Either "static" or "vue" . Default is "static" |
richTextType | One of "" , "block" , "blockAndInline" , or "inline" . When set, defines how the user can use the Component in Rich Text Fields. Default is "" |
isEnabled | Set this to false to disable the Component, but the user can override this value |
#Body Properties
Name | Description |
---|---|
lang | Language to use for the body. Either "html" or "pug" . Default is "pug" |
body | Body HTML/Pug. Do not use minification for this. The user should be able to read it to understand what it does so they can easily provide their own CSS, wrapper Components, and understand how the Component's Slots work |
#Style Properties
Name | Description |
---|---|
styleLang | Language to use for the style. Either "css" or "stylus" . Default is "stylus" |
style | Style CSS/Stylus. Do not use minification for this. The user should be able to read it to understand how variables are used, write their own CSS, etc. |
#Fields
Under the hood, Component Attributes are called Fields. This is an array of objects with the following properties:
Name | Description |
---|---|
name | The name of the Field. For example, a Field called "Per Page" would be entered as per-page="10" by the user when Templating |
type | One of "string" (Text), "multiline" (Text Area), "html" , "color" , "number" , "boolean" , "asset" , "media" , "enum" (Enumerable), "array" , or "object" . Default is "string" |
default | The default value to use if the Attribute isn't specified |
enumValues | A comma-separated list of values the Attribute the enum Field can accept. Only affects enum Fields. Example: "apple, banana, pear" |
description | A description of what the Attribute does, used in the the interface |
You can group these fields using objects within fieldGroups
with the following schema:
Name | Description |
---|---|
name | Optional group name. This is used as a heading above the group of Fields. |
description | Optional group description. This is used as text above the group of Fields. |
fields | An array of camelCase Field names in the order they should appear in the group. For example, if you have fields called "Main Color", "Secondary Color", and "Error Color", you would use ['mainColor', 'secondaryColor', 'errorColor'] |
You can also set displayField
on the Component to the name of the Attribute you want to be shown in Rich Text Fields. For example, if the Attribute name was "Cover Media ID", you could set displayField: "coverMediaId"
to use the value of that Attribute for the preview image when the Component is being used in a Rich Text Field.
#Tags
This is a list of Tags to add to any page the Component is on in the order they should be added. See Tags for more information.
Name | Description |
---|---|
name | The name of the Tag. For example: "Google Analytics" |
location | One of "head" , "bodyStart" , or "bodyEnd" . Default is "head" |
lang | The language of the tag body. Either "pug" or "html" . Default is "html" |
body | The HTML/Pug body of the Tag |
#Scripts
Name | Description |
---|---|
script | The script to be put on the any Page this Component is used on |
dataScript | The script used to create data used within the Component's Template |
buildScript | The script run for the Component at Build to generate Assets etc. |
#SEO Properties
Name | Description |
---|---|
seoLang | Language to use for the SEO body. Either "html" or "pug" . Only applies to Vue Components. Default is "pug" |
seoBody | SEO body HTML/Pug. Do not use minification for this. Only applies to Vue Components |
#Help
Help is an array of objects representing each of the Component's Help Pages with the following properties:
Name | Description |
---|---|
name | The Help Page's name |
path | The Help Page's path. For example: "/" |
body | Markdown for the Help Page's body |
#Authoring Addon Components
Trying to write body
, style
, script
, dataScript
, and buildScript
within your code is very difficult. It is recommended you first write and test the Component in MercuryCMS, then export it as a zip. You can then include the exported component.zip
file in your Addon Package.
#Creating Components
You can create Components by using cms.upsertComponent()
. This function will look to see if a specific Component exists and update it, or create it if it doesn't exist.
let componentDef = {
name: 'My Component',
description: 'A Demo Component',
type: 'static',
body: '.my-component This is a demo!',
style: '.my-component\n color {{ attr.color }}',
fields: [
{name: 'Color', type: 'color', default: '#ff0000', description: 'Text color'},
],
}
// use static-cms-addon
import cms from 'static-cms-addon'
let component = await cms.upsertComponent({name: 'My Component'}, componentDef, 'Added Color Attribute.')
console.log(component._id) // "63a0db9dd37c3735b468e1f8"
// use axios
let response = await axios.post(`http://localhost:${cmsPort}/api/addon/${addonId}/component`, {match: {name: 'My Component'}, component: componentDef, publishComment: 'Added Color Attribute.'})
console.log(response.data.component._id) // "63a0db9dd37c3735b468e1f8"
The first argument to upsertComponent()
is the fields to match against. This should typically just be name
. The second argument is the Component definition, and the third argument is an optional Publish Comment. You can use this to provide information about what changed in the Component. This will not be used if the Component is new, and will only be shown if the Component you are upserting has actually changed.
You can also load the Component from a zip or folder using cms.loadComponentPackage()
.
let componentDef = cms.loadComponentPackage('components/myComponent.component.zip').component
let component = await cms.upsertComponent({match: componentDef.name}, componentDef)
#Listing Components
You can use cms.getComponents()
to get a list of the Components your Addon has created.
// use static-cms-addon
import cms from 'static-cms-addon'
let components = await cms.getComponents()
console.log(components.map(component => component.name)) // ['My Component', 'Another Component']
// use axios
let response = await axios.get(`http://localhost:${cmsPort}/api/addon/${addonId}/component`)
console.log(response.data.components.map(component => component.name)) // ['My Component', 'Another Component']
#Deleting Components
You can use cms.deleteComponents()
to delete Components your Addon has created.
// use static-cms-addon
import cms from 'static-cms-addon'
let components = await cms.getComponents()
let component = components.find(component => component.name == 'My Component')
await cms.deleteComponents([component._id])
// use axios
let response = await axios.get(`http://localhost:${cmsPort}/api/addon/${addonId}/component`)
let component = response.data.components.find(component => component.name == 'My Component')
await axios.post(`http://localhost:${cmsPort}/api/addon/${addonId}/component/delete`, {componentIds: [component._id]})
#User Modification
Users cannot modify your Components, but they are expected to use them in a number of ways:
- Users can use your Component within their own Pages, Layouts, Components, and RichText Fields in Collections.
- Users can provide your Component Attributes whenever they use it, including creating a wrapper Component to set Attributes. MercuryCMS also allows the user to override any of your Component's default Attribute values. These settings are stored outside of the Component itself, so you can safely delete the Component and replace it with an updated version and the user's Attribute overrides will be retained.
- Users can put HTML content into your Slots. You should provide as many Slots as you can so users can easily add content their site needs without having to disable your Component and write their own custom version that won't be updated when the Addon is updated.
- Users can write their own CSS to override your Component's CSS, but you should make these options available as Attributes so you can easily change your Component's CSS without breaking the user's site.
- It is recommended you set variables as default values. For example, you can use
{{ addon.myaddon.settings.postsPerPage }}
as the default value for theper-page
Attribute. The user can now change this through your Addon's settings Screen, or can use their own value from their own Collections, Build Script, etc.