Open and Close a Breakout Editor

To open the modal window for the breakout editor, we recommend using a callback on event emission approach, which manages the asynchronous breakout editor process. If you have multiple breakout editors, the callback on event emission approach makes it easier to keep track of open breakout editors because a callback is related to only one breakout process.

This example opens the breakout editor from the trigger editor, waits for the user to close the breakout editor, and then gets the selected value.

// Code in the client-side JavaScript file for the trigger editor
(() => {
  // 1)
  subscribe('sfcc:ready', () => {
    // Once the editor is ready, a `sfcc:breakout` event is sent. Usually
    // this happens when a user clicks on a certain <button> or interacts with the trigger editor in some way
    const openButtonEl = document.querySelector('#myOpenBtn');
    openButtonEl.addEventListener('click', handleBreakoutOpen);
  });

  function handleBreakoutOpen() {
    // 2)
    // The user interacted with the <button> and the triggering editor requests that Page Designer
    // open a breakout on its behalf using an editor ID. This ID refers
    // to the key under which an editor has been put into the "dependencies" key-
    // value store of the triggering editor's configuration. A callback is provided
    // along with the event emission to be invoked once the breakout editor gets
    // closed.
    emit({
      type: 'sfcc:breakout',
      payload: {
        id: 'myCustomEditorId',
        title: 'The title to be displayed in the modal'
      }
    }, handleBreakoutClose);
  }

  function handleBreakoutClose({ type, value }) {
    // 5)
    // When the breakout is closed (either programmatically, or via the
    // built-in action <button>s), the callback is invoked, containing
    // information about the "type" of action that caused the invocation.
    // A breakout can be closed with the intent to either "Cancel" or "Apply"
    // an editing process. The intent can be derived from the "type" information
    // that comes as part of the callback reponse (either `sfcc:breakoutCancel`
    // or `sfcc:breakoutApply`). In case of an "Apply" intent will also include
    // a "value" available as part of the response, reflecting the value that has
    // last been set via `sfcc:value` in the breakout editor.

    // Now the "value" can be passed back to Page Designer
    if (type === 'sfcc:breakoutApply') {
      handleBreakoutApply(value);
    } else {
      handleBreakoutCancel();
    }
  }

  function handleBreakoutCancel() {
    // ...
  }

  function handleBreakoutApply(value) {
    // ...

    // Emit value update to Page Designer host application
    emit({
      type: 'sfcc:value',
      payload: value
    });
  }
})();
// Code in the client-side JavaScript file for the breakout editor
(() => {
  // 3)
  subscribe('sfcc:ready', () => {
    // Once the breakout editor is ready, the custom code is able to select or create
    // a value. Any meaningful change to a value/selection needs to be reflected
    // back into the host container via a `sfcc:value` event.
    const selectEl = document.querySelector('#mySelect');
    selectEl.addEventListener('change', handleSelect);
  });

  function handleSelect({ target }) {
    // 4)
    // The value changed and the breakout editor's host is informed about the
    // value update via a `sfcc:value` event.
    const selectedValue = target.value;
    emit({
      type: 'sfcc:value',
      payload: selectedValue ? { value: selectedValue } : null
    });    
  }
})();
Another way to open and close the breakout modal is to use only events. However, this approach is more difficult because it requires that you correctly implement a cascade of subscribers and emitters based on the messaging API. This example illustrates a trigger editor that manages multiple parallel breakdout editors.
Note: If you leave the ID portion of an event payload blank, Page Designer closes the first open breakout editor related to the requesting trigger editor. `
// Code in the client-side JavaScript file for the trigger editor
(() => {
  // 1)
  subscribe('sfcc:ready', () => {
    // Once the editor is ready, a `sfcc:breakout` event can be sent. Usually
    // this happens when a user clicks on a certain <button> or interacts with the trigger editor in some way
    const openButtonEl = document.querySelector('#myOpenBtn');
    openButtonEl.addEventListener('click', handleBreakoutOpen);
  });

  // 3b)
  subscribe('sfcc:breakout', ({ id }) => {
    // Once the Page Designer host application opens a breakout on the trigger editor's behalf,
    // it informs the trigger about its newly created breakout via a `sfcc:breakout`
    // event. The important property of the payload is the "id" which can be stored
    // to be used later to explicitly close a certain breakout component. There is
    // no hard requirement listening to this event in case the custom code inside
    // the triggering editor doesn't have to explicitly close a certain breakout
    // programmatically. Usually a breakout will be closed by the breakout itself,
    // either via the custom code inside the breakout CAE, or via user interaction
    // with a built-in <button> in a breakout's footer section.
  });

  // 6a)
  subscribe('sfcc:breakoutCancel', ({ id,  }) => {
    // ...
  });

  // 6b)
  subscribe('sfcc:breakoutApply', ({ id, value }) => {
    // ...

    // Emit value update to Page Designer
    emit({
      type: 'sfcc:value',
      payload: value
    });
  });

  function handleBreakoutOpen() {
    // 2)
    // The user interacted with the <button> and the triggering CAE requests that Page Designer
    // open a breakout on its behalf using a certain editor ID. This ID refers
    // to the key under which an editor has been put into the "dependencies" key-
    // value store of the triggering editor's configuration. This time no callback
    // is provided along with the event emission.
    emit({
      type: 'sfcc:breakout',
      payload: {
        id: 'myCustomEditorId',
        title: 'The title to be displayed in the modal'
      }
    });
  }
})();
// Code in the client-side JavaScript file for the breakout editor
(() => {
  // 3a)
  subscribe('sfcc:ready', ({ breakout }) => {
    // Along with the `sfcc:ready` event, some meta information about the breakout is
    // passed to the breakout editor. The important property in the "breakout" data
    // is the "id" which can be stored to be used later to explicitly close a
    // certain breakout component.

    // Once the breakout editor is ready, the custom code is able to select or create
    // a value. Any meaningful change to a value or selection must be reflected
    // back into the host container via a `sfcc:value` event.
  
    // 3)
    // Apply event handlers to elements inside the component's DOM.
    // It's not required to have action buttons inside the editor itself as the
    // surrounding breakout element's footer section already contains <button>
    // elements for both "Cancel" and "Apply" actions.
    const cancelButtonEl = document.querySelector('#myCancelBtn');
    const applyButtonEl = document.querySelector('#myApplyBtn');
    const selectEl = document.querySelector('#mySelect');
    const { id } = breakout;
    cancelButtonEl.addEventListener('click', () => handleBreakoutCancel(id));
    applyButtonEl.addEventListener('click', () => handleBreakoutApply(id));
    selectEl.addEventListener('change', handleSelect);
  });

  function handleSelect({ target }) {
    // 4)
    // The value changed and the breakout editor's host gets informed about the
    // value update via a `sfcc:value` event.
    const selectedValue = target.value;
    emit({
      type: 'sfcc:value',
      payload: selectedValue ? { value: selectedValue } : null
    });    
  }

  function handleBreakoutCancel(id) {
    // 5a)
    // Explicitly request that the Page Designer host application close a certain breakout with
    // the intent to cancel the editing process.
    emit({
      type: 'sfcc:breakoutCancel',
      payload: { id }
    });
  }

  function handleBreakoutApply(id) {
    // 5b)
    // Explicitly request that the Page Designer host application close a certain breakout with
    // the intent to apply the current value/selection of the editing process.
    emit({
      type: 'sfcc:breakoutApply',
      payload: { id }
    });
  }
})();