Search code examples
node.jsapostrophe-cms

Stop callback chain and send notification beforeSave method ApostropheCMS


I'm trying to prevent the user to save a piece if it doesn't achieve some requirements.

Currently I'm doing it like this:

    self.beforeSave = function(req, piece, options, callback) {
      let success = true;
      let error = "";
      if (Array.isArray(piece._subevents) && piece._subevents.length) {
        success = self.checkDateAndTimeCompabilitiyWithChildren(piece);
      }
      if (!success) {
        self.apos.notify(req, "Check the compatibility between parent event and subevents", { type: "error" });
        error = "Subevents are not compatible with parent event";
      }
      callback(error);
    };

This works but the problem is it shows 2 errors notifications (the default and my custom), 1 because of callback(error) and 1 because of apos.notify.

Any idea how to stop the item of being saved and only show my notification?

Thanks in advance.

UPDATE 1: As Tom pointed out, my code looks like this now:

// lib/modules/events/public/js/editor-modal.js
apos.define('events-editor-modal', {
  extend: 'apostrophe-pieces-editor-modal',
  construct: function(self, options) {
    self.getErrorMessage = function(err) {
      if (err === 'incompatible') {
        apos.notify('A message suitable for this case.', { type: 'error' });
      } else {
        apos.notify('A generic error message.', { type: 'error' });
      }
    };
  }
});
// lib/modules/events/index.js
    var superPushAssets = self.pushAssets;
    self.pushAssets = function() {
      superPushAssets();
      self.pushAsset("script", "editor-modal", { when: "user" });
    };
    self.beforeSave = async function(req, piece, options, callback) {
      return callback("incompatible")
    };

For testing purposes I'm just returning the error in beforeSave. The problem is that an exception is being thrown in the browser console and the modal is not properly rendered again. Here's a screenshot about what I'm talking: enter image description here

I'm trying to debug it and understand what's happening but no clue yet.


Solution

  • In your server-side code:

        self.beforeSave = function(req, piece, options, callback) {
          let success = true;
          if (Array.isArray(piece._subevents) && piece._subevents.length) {
            success = self.checkDateAndTimeCompabilitiyWithChildren(piece);
          }
          if (!success) {
            return callback('incompatible');
          }
          return callback(null);
        };
    

    And on the browser side:

    // in lib/modules/my-pieces-module/public/js/editor-modal.js
    apos.define('my-pieces-module-editor-modal', {
      extend: 'apostrophe-pieces-editor-modal',
      construct: function(self, options) {
        self.getErrorMessage = function(err) {
          if (err === 'incompatible') {
            return 'A message suitable for this case.';
          } else {
            return 'A generic error message.';
          }
        };
      }
    });
    

    If the error reported by the callback is a string, it is passed to the browser. The browser can then recognize that case and handle it specially. 'my-pieces-module-editor-modal' should be substituted with the name of your pieces module followed by -editor-modal.