27
loading...
This website collects cookies to deliver better user experience
This guide focuses on how to customize Apostrophe's administrative user interface, or "admin UI." The built-in functionality covers most situations, but sometimes you'll want to add or change functionality.
.vue
files across various Apostrophe modules. These are typically found in Apostrophe core, but they can be anywhere in the project. This means that we can introduce our own Vue components to the admin UI just by adding .vue
files to the ui/apos/components
subdirectory of any Apostrophe module. As explained below, it is also possible to override existing components by supplying a component with the same name.APOS_DEV=1 npm run dev
export APOS_DEV=1
review
that takes advantage of the starRating field type we define in a separate article. We'll add a rating
field to the schema for the piece type, and also add a column to display it in the manager modal:module.exports = {
extend: '@apostrophecms/piece-type',
fields: {
add: {
rating: {
type: 'starRating',
label: 'Star Rating',
required: true
}
}
},
columns: {
// 👇 Columns are a "cascade" just like fields,
// we have an "add" property with a subproperty
// for each column
add: {
rating: {
// 👇 Each column has a label property and a
// component property. The component name must
// exist as a Vue component
label: 'Rating',
component: 'ColumnStarRating'
}
}
}
};
ColumnStarRating
, that doesn't exist yet. Next we'll introduce that component:<template>
<p
class="apos-table__cell-field"
:class="`apos-table__cell-field--${header.name}`"
>
<span v-if="hasValue">
<span v-for="index in 5" :key="index" class="rating">{{ isActive(index) ? '☆' : '★' }}</span>
</span>
<span v-else>
None
</span>
</p>
</template>
<script>
import AposCellMixin from 'Modules/@apostrophecms/ui/mixins/AposCellMixin';
export default {
name: 'AposCellBasic',
mixins: [ AposCellMixin ],
computed: {
hasValue() {
return this.get(this.header.name) != null;
}
},
methods: {
isActive(index) {
return index <= (this.get(this.header.name) || 0);
}
}
};
</script>
star-range-field
module because it might be used as a column in any piece type, not just a review
.AposCellMixin
to do two important things:header
prop, which is automatically declared by the mixin.this.get
with any property name. Following Apostrophe's convention this method automatically fetches from the published version of the piece if it exists, otherwise from the draft.ui/apos/components
subdirectory of a project-level module. You can also do this in a custom npm module to achieve reuse across projects.NOTE: For more information about the patterns used, props provided and APIs needed to override an existing core component, it's necessary to study the source code of the original.
AposDocsManager
component definition in a project, but sometimes we need different behavior for a specific piece type. We could work around this by overriding a core component and adding conditional logic, but this results in code that is hard to maintain, and also means we are stuck maintaining a copy of a complex component and missing out on bug fixes and improvements. It would be better to specify a different, custom component name to be used to manage a particular piece type.module.exports = {
extend: '@apostrophecms/piece-type',
options: {
components: {
managerModal: 'AnnouncementManager'
}
}
}
AnnouncementManager
when the user selects "Announcements" from the admin bar, bypassing AposDocManager
.modules/announcement/ui/apos/components/AnnouncementManager.vue
.@apostrophecms/piece-type
it can be used for any module that extends it.@apostrophecms/page
module. Piece and widget types can have their own type-specifc overrides.Modal
, the component is required to embed the AposModal
component. For examples, look at the source code of the default components listed above.AposWidgetEditor
component already provides a modal dialog box in which to edit the schema of any widget, so we won't need to configure a replacement unless we want to support editing directly on the page. AposRichTextWidgetEditor
is an example of how to do this.AposWidget
component has nothing to do with a typical site visitor experience. It is used only when displaying our widget while the page is in edit mode. While overriding this component is rare, the @apostrophecms/rich-text-widget
module does so to provide a "click the text to edit" experience for rich text widgets. If you're just trying to enhance your widget with frontend JavaScript, you should write a widget player instead.