问题
In an ApostropheCMS application, we have a piece type "book". The front-end users are able, from the CMS, to update fields declared in the piece's index.js
.
We need to dynamically add or update a field once the user saves, namely a citations
field. We use Citation.js to generate MLA, Chicago, etc. citations according to what the editor has entered in the CMS.
We don't want to make this field visible in the CMS, because it needs to always be overwritten by the Citation.js generated results. (If there is a way to add a field and hide it from the CMS, that would be a great solution!).
Our current idea is to add the field (if it's missing) or update it (if it exists) on save:
(mostly) pseudo code
self.on('apostrophe-docs:afterSave', 'updateBook', async (req) => {
const { piece } = req;
// fetch citations
const citations = { ... };
// create update piece
const updated = _.cloneDeep(piece);
updated.citations = citations;
// check if citations field already present
if (!('citations' in piece)) {
// add citations field
// should method be different if field doesnt exist yet?
self.update(req, updated);
} else {
// check when citations were last updated to ensure enough time diff to update
// update citations field if all is well
self.update(req, updated);
}
});
As expected, this currently creates an infinite loop because 'apostrophe-docs:afterSave'
is called after calling self.update
.
- Is there a way to pass a param to prevent that callback?
- Otherwise, we were thinking about checking when the last
update()
occurred, any better suggestion?
- Otherwise, we were thinking about checking when the last
- Does
update()
not add fields that are on the piece passed to the method? Does it only care about fields defined in theindex.js
?
Any suggestion on how to achieve that is welcome.
回答1:
beforeSave
is more likely what you should use. You won't need to call .update()
if you simply add the information onto the piece before it's actually saved to the db.
To your question about visibility, you don't need to add document properties to the piece schema to be able to save them. Fields need to be in the piece schema to be edited or viewed in the UI (even if set to readOnly: true
).
So in the construct step you could add something like:
self.on('books:beforeSave', 'populateCitation');
self.populateCitation = function (req, piece, options) {
// Being extra safe here.
if (piece.type !== 'book') {
return;
}
// Let's pretend `bookInfo`
if (piece.bookInfo) {
// `getCitation` would be a method using Citation.js
const citationInfo = getCitation(piece.bookInfo);
piece.citation = citationInfo;
}
};
You can then read the citation
property on the document in code and (I'm pretty sure) in the template as well, if it is present (make sure to check for it in the template before printing).
来源:https://stackoverflow.com/questions/64850545/how-to-add-update-piece-field-when-the-user-saves-commits