App


Toolbars Tutorials

Tutorial HomeToolbars

Advanced Toolbar Customizations

Important: Usually only editors see these toolbars - so saving won't work. Hover over the various boxes to see the result - like this:

The samples can differ based on your Razor base class or if you're running an old version.
Switch to Typed (2sxc 16+) Selected: Dynamic (Razor14 or below)

2sxc UI - Toolbar Workflows

Toolbars will automatically do things like open a dialog or refresh the page when the dialog closes. But sometimes you want to override or change the default behavior - like:

  1. Prevent refresh on dialog close - to retrieve the data in JS
  2. Prevent creating new if a specific condition applies

This is what the Workflows are for. You can register custom before and after code to run, change specs or prevent the action from executing. Read the workflow docs or the toolbar docs to learn more about this.

Float over this box to get a (+) button. When you click it and close the dialog again, the page will not refresh.
Instead, you'll see console messages that a custom JS took over the process.
@inherits Custom.Hybrid.Razor14

@{
    var standardToolbar = Kit.Toolbar.Empty().New("UiEmptyHelloWorld").Settings(show: "always");
  }
<div class="alert alert-primary" style="width: 100%;">
  <div id='tagWithToolbar' @standardToolbar>
    Float over this box to get a (+) button. 
    When you click it and close the dialog again, the page will <em>not refresh</em>. <br>
    Instead, you'll see console messages that a custom JS took over the process.
  </div>
</div>

Source Code of 130-toolbar-workflow.js

window.toolbarWorkflow = {
  // This workflow definition will run on every action, just to log what's happening
  workflowToLog: {
    command: 'all',   // Run on every command/action
    phase: 'all',     // Run before and after
    code: (wfArgs) => {
      console.log("Toolbar asked to to something - here are the details.", wfArgs);
    }
  },

  // This is the workflow definition we will register to stop page refresh
  workflowToDisableRefresh: {
    command: 'refresh',   // The command name it's for
    phase: 'before',      // The workflow-step should run before the command is executed
    code: (wfArgs) => {   // The code which should be run
        console.log('Toolbar asked to refresh, will return false to stop it. These are the arguments we got.', wfArgs);
        return false;       // Return false to stop this command from happening
    }
  },

  // Attach event-listener to the TagToolbar parent, so we can register the workflow when the toolbar is created
  initOnTagToolbar: function(name) {
    console.log('initInlineToolbar(' + name.data + ')');
    var parent = document.getElementById(name.data);
    console.log('parent:', parent);
    parent.addEventListener('toolbar-init', (initEvent) => {
      console.log("Workflow Demo: Tag Toolbar was initialized - event kicked in - will now register");
      const workflow = initEvent.detail.workflow;

      workflow.add(window.toolbarWorkflow.workflowToLog);
      workflow.add(window.toolbarWorkflow.workflowToDisableRefresh);

      // Stop the event here, otherwise parent elements which have an event listener would get triggered as well
      initEvent.stopPropagation();
    });
  },

  // Attach event-listener to the parent of the inline-toolbar, so we can register the workflow when the toolbar is created
  initInlineToolbar: function(name) {
    console.log('initInlineToolbar(' + name.data + ')');
    var parent = document.getElementById(name.data);
    console.log('parent:', parent);
    parent.addEventListener('toolbar-init', (initEvent) => {
      console.log("Workflow Demo: Inline Toolbar was initialized - event kicked in - will now register");
      const workflow = initEvent.detail.workflow;

      workflow.add(window.toolbarWorkflow.workflowToLog);
      workflow.add(window.toolbarWorkflow.workflowToDisableRefresh);

      // Stop the event here, otherwise parent elements which have an event listener would get triggered as well
      initEvent.stopPropagation();
    }); 
  }

}

When you click it and close the dialog again, the page will not refresh.
Instead, you'll see console messages that a custom JS took over the process.
@inherits Custom.Hybrid.Razor14

<div class="alert alert-primary" style="width: 100%;">
  <div id='inlineToolbar'>
    @Kit.Toolbar.Empty().New("UiEmptyHelloWorld").AsTag()
    When you click it and close the dialog again, the page will <em>not refresh</em>. <br>
    Instead, you'll see console messages that a custom JS took over the process.
  </div>
</div>

Source Code of 130-toolbar-workflow.js

window.toolbarWorkflow = {
  // This workflow definition will run on every action, just to log what's happening
  workflowToLog: {
    command: 'all',   // Run on every command/action
    phase: 'all',     // Run before and after
    code: (wfArgs) => {
      console.log("Toolbar asked to to something - here are the details.", wfArgs);
    }
  },

  // This is the workflow definition we will register to stop page refresh
  workflowToDisableRefresh: {
    command: 'refresh',   // The command name it's for
    phase: 'before',      // The workflow-step should run before the command is executed
    code: (wfArgs) => {   // The code which should be run
        console.log('Toolbar asked to refresh, will return false to stop it. These are the arguments we got.', wfArgs);
        return false;       // Return false to stop this command from happening
    }
  },

  // Attach event-listener to the TagToolbar parent, so we can register the workflow when the toolbar is created
  initOnTagToolbar: function(name) {
    console.log('initInlineToolbar(' + name.data + ')');
    var parent = document.getElementById(name.data);
    console.log('parent:', parent);
    parent.addEventListener('toolbar-init', (initEvent) => {
      console.log("Workflow Demo: Tag Toolbar was initialized - event kicked in - will now register");
      const workflow = initEvent.detail.workflow;

      workflow.add(window.toolbarWorkflow.workflowToLog);
      workflow.add(window.toolbarWorkflow.workflowToDisableRefresh);

      // Stop the event here, otherwise parent elements which have an event listener would get triggered as well
      initEvent.stopPropagation();
    });
  },

  // Attach event-listener to the parent of the inline-toolbar, so we can register the workflow when the toolbar is created
  initInlineToolbar: function(name) {
    console.log('initInlineToolbar(' + name.data + ')');
    var parent = document.getElementById(name.data);
    console.log('parent:', parent);
    parent.addEventListener('toolbar-init', (initEvent) => {
      console.log("Workflow Demo: Inline Toolbar was initialized - event kicked in - will now register");
      const workflow = initEvent.detail.workflow;

      workflow.add(window.toolbarWorkflow.workflowToLog);
      workflow.add(window.toolbarWorkflow.workflowToDisableRefresh);

      // Stop the event here, otherwise parent elements which have an event listener would get triggered as well
      initEvent.stopPropagation();
    }); 
  }

}

Use cms.run() to call Toolbar Commands from JS-Events

In some cases you need to call a CMS command without using the toolbar - like in SPAs and in situations where a normal HTML button should call edit. You can also use this to trigger Workflows (new in 12.10).

You can register custom before and after code to run, change specs or prevent the action from executing. Read the workflow docs or the toolbar docs to learn more about this.

The following command will open an edit dialog. When you click it and close the dialog again, the page will not refresh.
Instead, you'll see console messages that a custom JS took over the process.
👉 Run open command
@inherits Custom.Hybrid.Razor14

<div class="alert alert-primary" style="width: 50%;">
    The following command will open an edit dialog. 
    When you click it and close the dialog again, the page will <em>not refresh</em>. <br>
    Instead, you'll see console messages that a custom JS took over the process. <br>

    <a href="#" onclick="openAndCancelRefreshAfterwards(this, event, 'new', { contentType: 'UiEmptyHelloWorld'})">👉 Run open command</a>
</div>

<script src="@App.Path/ui/run/160-cms-run-commands.js" @Kit.Page.AssetAttributes()></script>

Source Code of 160-cms-run-commands.js

function openAndCancelRefreshAfterwards(tag, event, action, params) {
  // Prevent the click from propagating, so the link won't execute href
  event.preventDefault();

  // This workflow step will run on every action, just to log what's happening
  const workflowToLog = {
    command: 'all',   // Run on every command/action
    phase: 'all',     // Run before and after
    code: (wfArgs) => {
      console.log("Toolbar asked to to something - here are the details.", wfArgs);
    }
  }

  // This is the workflow step we will register to stop page refresh
  const workflowToDisableRefresh = {
    command: 'refresh',   // The command name it's for
    phase: 'before',      // The workflow-step should run before the command is executed
    code: (wfArgs) => {   // The code which should be run
      console.log('Toolbar asked to refresh, will return false to stop it. These are the arguments we got.', wfArgs);
      return false;       // Return false to stop this command from happening
    }
  };

  $2sxc(tag).cms.run({ action: action, params: params, workflows: [workflowToLog, workflowToDisableRefresh]})
    .then(function(data) {
      console.log("after run", data);
      return false;
    });
  
}