Skip to main content
Home  › ... Razor

Customize Edit UI/UX

Tutorial HomeCustomize Edit UX

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.

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

Standard TagToolbar

Output

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.
@{
    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();
    }); 
  }

}

Standard Inline Toolbar

Output

    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.
    <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();
        }); 
      }
    
    }

    More Stuff

    You can do much more - like change icons, call call-parameters etc. Read the how-to and the specs for this.

    Source Code of this file

    Below you'll see the source code of the file. Note that we're just showing the main part, and hiding some parts of the file which are not relevant for understanding the essentials. Click to expand the code

    @inherits Custom.Hybrid.Razor14
    <!-- unimportant stuff, hidden -->
    
    
    <div @Sys.PageParts.InfoWrapper()>
      @Html.Partial("../shared/DefaultInfoSection.cshtml")
      <div @Sys.PageParts.InfoIntro()>
        <h2>2sxc UI - Toolbar Workflows</h2>
        <p>
          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:
        </p>
        <ol>
          <li>Prevent refresh on dialog close - to retrieve the data in JS</li>
          <li>Prevent creating new if a specific condition applies</li>
        </ol>
        <p>
          This is what the Workflows are for. You can register custom <code>before</code> and <code>after</code> code to run, change specs or prevent the action from executing. 
          <a href="https://r.2sxc.org/js-workflow" target="_blank">Read the workflow docs</a> or the 
          <a href="https://docs.2sxc.org/how-to/customize-edit-ux/toolbars.html" target="_blank">toolbar docs</a> to learn more about this. 
        </p>
      </div>
    </div>
    
    <div class="alert alert-warning">
      Important: Usually only editors see these toolbars - so saving won't work. 
      Hover over the various boxes to see the result - like this: <br>
      <img loading="lazy" src="@App.Path/ui/assets/hover-example.jpg" width="100%">
    </div>
    @Html.Partial("../shared/WarnAnonymousIfFeatureIsOff.cshtml")
    
    
    </hide>
    <div class="alert alert-success">
    
      <h2>Standard TagToolbar</h2>
    
      @{
          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>
    
    
    
    <div class="alert alert-success">
      <h2>Standard Inline Toolbar</h2>
    
      <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>
    
    
    
    <!-- unimportant stuff, hidden -->
    
     @* This tutorial uses turnOn, see turnOn tutorials *@
      @{
        var onTag = new {
          data = "tagWithToolbar"
        };
         var inline = new {
          data = "inlineToolbar"
        };
      }
      @Kit.Page.TurnOn("window.toolbarWorkflow.initOnTagToolbar()", data: onTag)
      @Kit.Page.TurnOn("window.toolbarWorkflow.initInlineToolbar()", data: inline)
    
    <script src="@CmsContext.View.Path/130-toolbar-workflow.js" @Kit.Page.AssetAttributes()></script>
    
    @* 2sxclint:disable:no-inline-script *@
    @* Footer *@
    @Html.Partial("../Shared/Layout/FooterWithSource.cshtml", new { Sys = Sys })