Search results

Integration with Toolbar in React Signature component

02 Feb 2023 / 5 minutes to read

The Signature component integrates with the toolbar and the interaction performed using the change event of the toolbar. In that, canUndo, canRedo and isEmpty methods were used to enable/disable undo, redo, and clear buttons.

Source
Preview
index.jsx
index.html
index.tsx
Copied to clipboard
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import { ColorPickerComponent } from '@syncfusion/ej2-react-inputs';
import { SignatureComponent } from '@syncfusion/ej2-react-inputs';
import { getComponent, createElement, addClass } from '@syncfusion/ej2-base';
import { ItemDirective, ItemsDirective, ToolbarComponent } from '@syncfusion/ej2-react-navigations';
import { CheckBox } from '@syncfusion/ej2-buttons';
import { SplitButtonComponent } from '@syncfusion/ej2-react-splitbuttons';
import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns';
function App() {
    let signature;
    let disabledTemplate = new CheckBox({ label: 'Disabled', checked: false, change: change });
    function change(args) {
        let signature = getComponent(document.getElementById('signature'), 'signature');
        signature.disabled = args.checked;
    }
    function onCreated() {
        let strokeColor = getComponent(document.getElementById('stroke-color'), 'colorpicker');
        let bgColor = getComponent(document.getElementById('bg-color'), 'colorpicker');
        addClass([strokeColor.element.nextElementSibling.querySelector('.e-selected-color')], 'e-sign-icons');
        addClass([bgColor.element.nextElementSibling.querySelector('.e-selected-color')], 'e-sign-icons');
        document.getElementById('save-option').addEventListener('click', saveBtnClick);
        clearButton();
        let toolbarlItems = document.querySelectorAll('.e-toolbar .e-toolbar-items .e-toolbar-item .e-tbar-btn.e-tbtn-txt');
        for (var i = 0; i < toolbarlItems.length; i++) {
            if (toolbarlItems[i].children[0].classList.contains('e-undo')) {
                let undoButton = getComponent(toolbarlItems[i], 'btn');
                undoButton.disabled = true;
            }
            if (toolbarlItems[i].children[0].classList.contains('e-redo')) {
                let redoButton = getComponent(toolbarlItems[i], 'btn');
                redoButton.disabled = true;
            }
        }
    }
    function onClicked(args) {
        let signature = getComponent(document.getElementById('signature'), 'signature');
        let saveBtn = getComponent(document.getElementById("save-option"), 'split-btn');
        if (signature.disabled && args.item.tooltipText != 'Disabled') {
            return;
        }
        switch (args.item.tooltipText) {
            case 'Undo (Ctrl + Z)':
                if (signature.canUndo()) {
                    signature.undo();
                    updateUndoRedo();
                    updateSaveBtn();
                }
                break;
            case 'Redo (Ctrl + Y)':
                if (signature.canRedo()) {
                    signature.redo();
                    updateUndoRedo();
                    updateSaveBtn();
                }
                break;
            case 'Clear':
                signature.clear();
                if (signature.isEmpty()) {
                    clearButton();
                    saveBtn.disabled = true;
                }
                break;
        }
    }
    function onChange() {
        let signature = getComponent(document.getElementById('signature'), 'signature');
        let saveBtn = getComponent(document.getElementById("save-option"), 'split-btn');
        if (!signature.isEmpty()) {
            clearButton();
            saveBtn.disabled = false;
        }
        updateUndoRedo();
    }
    function saveBtnClick() {
        let signature = getComponent(document.getElementById("signature"), 'signature');
        signature.save();
    }
    function clearButton() {
        let signature = getComponent(document.getElementById('signature'), 'signature');
        let tlItems = document.querySelectorAll('.e-toolbar .e-toolbar-items .e-toolbar-item .e-tbar-btn.e-tbtn-txt');
        for (var i = 0; i < tlItems.length; i++) {
            if (tlItems[i].children[0].classList.contains('e-clear')) {
                let clrBtn = getComponent(tlItems[i], 'btn');
                if (signature.isEmpty()) {
                    clrBtn.disabled = true;
                }
                else {
                    clrBtn.disabled = false;
                }
            }
        }
    }
    function updateSaveBtn() {
        let signature = getComponent(document.getElementById('signature'), 'signature');
        let saveBtn = getComponent(document.getElementById("save-option"), 'split-btn');
        if (signature.isEmpty()) {
            saveBtn.disabled = true;
        }
        else {
            saveBtn.disabled = false;
        }
    }
    function updateUndoRedo() {
        let signature = getComponent(document.getElementById('signature'), 'signature');
        let undoButton;
        let redoButton;
        let tlItems = document.querySelectorAll('.e-toolbar .e-toolbar-items .e-toolbar-item .e-tbar-btn.e-tbtn-txt');
        for (var i = 0; i < tlItems.length; i++) {
            if (tlItems[i].children[0].classList.contains('e-undo')) {
                undoButton = getComponent(tlItems[i], 'btn');
            }
            if (tlItems[i].children[0].classList.contains('e-redo')) {
                redoButton = getComponent(tlItems[i], 'btn');
            }
        }
        if (signature.canUndo()) {
            undoButton.disabled = false;
        }
        else {
            undoButton.disabled = true;
        }
        if (signature.canRedo()) {
            redoButton.disabled = false;
        }
        else {
            redoButton.disabled = true;
        }
    }
    function saveTemplate() {
        let items;
        items = [
            {
                text: 'Png'
            },
            {
                text: 'Jpeg'
            },
            {
                text: 'Svg'
            }
        ];
        function onSelect(args) {
            let signature = getComponent(document.getElementById('signature'), 'signature');
            signature.save(args.item.text, 'Signature');
        }
        return (<div>
          <SplitButtonComponent content="Save" id="save-option" items={items} iconCss='e-sign-icons e-save' select={onSelect} disabled={true}/>
      </div>);
    }
    function strokeColorTemplate() {
        let presets;
        presets = {
            'custom': ['#000000', '#e91e63', '#9c27b0', '#673ab7', '#2196f3', '#03a9f4', '#00bcd4',
                '#009688', '#8bc34a', '#cddc39', '#ffeb3b', '#ffc107']
        };
        function tileRender(args) {
            args.element.classList.add('e-circle-palette');
            args.element.appendChild(createElement('span', { className: 'e-circle-selection' }));
        }
        function strokeColorChanged(args) {
            let signature = getComponent(document.getElementById('signature'), 'signature');
            let strokeColor = getComponent(document.getElementById('stroke-color'), 'colorpicker');
            if (signature.disabled) {
                return;
            }
            let selElem = strokeColor.element.nextElementSibling.querySelector('.e-selected-color');
            selElem.style.borderBottomColor = args.currentValue.rgba;
            signature.strokeColor = args.currentValue.rgba;
        }
        return (<div>
          <ColorPickerComponent id="stroke-color" mode='Palette' cssClass='e-stroke-color' modeSwitcher={false} showButtons={false} columns={4} presetColors={presets} beforeTileRender={tileRender} change={strokeColorChanged}></ColorPickerComponent>
      </div>);
    }
    function bgColorTemplate() {
        let presets;
        presets = {
            'custom': ['#ffffff', '#f44336', '#e91e63', '#9c27b0', '#673ab7', '#2196f3', '#03a9f4', '#00bcd4',
                '#009688', '#8bc34a', '#cddc39', '#ffeb3b']
        };
        function beforeTileRender(args) {
            args.element.classList.add('e-circle-palette');
            args.element.appendChild(createElement('span', { className: 'e-circle-selection' }));
        }
        function bgColorChanged(args) {
            let signature = getComponent(document.getElementById('signature'), 'signature');
            let bgColor = getComponent(document.getElementById('bg-color'), 'colorpicker');
            if (signature.disabled) {
                return;
            }
            let selElem = bgColor.element.nextElementSibling.querySelector('.e-selected-color');
            signature.backgroundColor = args.currentValue.rgba;
            selElem.style.borderBottomColor = args.currentValue.rgba;
        }
        return (<div>
          <ColorPickerComponent id="bg-color" noColor={true} mode='Palette' cssClass='e-bg-color' modeSwitcher={false} showButtons={false} columns={4} presetColors={presets} beforeTileRender={beforeTileRender} change={bgColorChanged}></ColorPickerComponent>
      </div>);
    }
    function strokeWidthTemplate() {
        let data = [1, 2, 3, 4, 5];
        let value = 2;
        function strokeWidthChanged(args) {
            let signature = getComponent(document.getElementById('signature'), 'signature');
            signature.maxStrokeWidth = args.value;
        }
        return (<div>
          <DropDownListComponent id="ddlelement" dataSource={data} value={value} width="60" change={strokeWidthChanged}/>
      </div>);
    }
    return (<div className='control-pane'>
          <div className="col-lg-12 control-section">
              <div id="signature-toolbar-control">
                  <ToolbarComponent id='toolbar' created={onCreated} clicked={onClicked}>
                      <ItemsDirective>
                          <ItemDirective text='Undo' prefixIcon='e-icons e-undo' tooltipText='Undo (Ctrl + Z)'/>
                          <ItemDirective text='Redo' prefixIcon='e-icons e-redo' tooltipText='Redo (Ctrl + Y)'/>
                          <ItemDirective type='Separator'/>
                          <ItemDirective tooltipText='Save (Ctrl + S)' type='Button' template={saveTemplate}/>
                          <ItemDirective type='Separator'/>
                          <ItemDirective tooltipText='Stroke Color' template={strokeColorTemplate}/>
                          <ItemDirective type='Separator'/>
                          <ItemDirective tooltipText='Background Color' template={bgColorTemplate}/>
                          <ItemDirective type='Separator'/>
                          <ItemDirective tooltipText='Stroke Width' template={strokeWidthTemplate}/>
                          <ItemDirective type='Separator'/>
                          <ItemDirective text='Clear' prefixIcon='e-sign-icons e-clear' tooltipText='Clear'/>
                          <ItemDirective tooltipText='Disabled' type='Input' template={disabledTemplate} align='Right'/>
                      </ItemsDirective>
                  </ToolbarComponent>
                  <div id="signature-control">
                      <SignatureComponent maxStrokeWidth={2} id="signature" change={onChange}></SignatureComponent>
                  </div>
              </div>
          </div>
      </div>);
}
export default App;
ReactDOM.render(<App />, document.getElementById('element'));
Copied to clipboard
<!DOCTYPE html>
<html lang="en">

<head>
            
    <title>EJ2 React Signature</title>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <meta name="description" content="React Signature Component" />
    <meta name="author" content="Syncfusion" />
    <link href="styles.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/20.4.48/ej2-base/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/20.4.48/ej2-inputs/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/20.4.48/ej2-buttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/20.4.48/ej2-splitbuttons/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/20.4.48/ej2-navigations/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/20.4.48/ej2-dropdowns/styles/material.css" rel="stylesheet" />
    <link href="//cdn.syncfusion.com/ej2/20.4.48/ej2-popups/styles/material.css" rel="stylesheet" />
    <script src="https://cdnjs.cloudflare.com/ajax/libs/systemjs/0.19.38/system.js"></script>
    <script src="systemjs.config.js"></script>
</head>

<body>
    <div id='element'>
        <div id='loader'>Loading....</div>
    </div>
</body>

</html>
Copied to clipboard
import * as ReactDOM from 'react-dom';
import * as React from 'react';
import { ColorPicker, ColorPickerComponent, ColorPickerEventArgs, PaletteTileEventArgs } from '@syncfusion/ej2-react-inputs';
import { SignatureFileType, Signature, SignatureComponent } from '@syncfusion/ej2-react-inputs';
import { Button} from '@syncfusion/ej2-react-buttons';
import { getComponent, createElement, addClass } from '@syncfusion/ej2-base';
import { ClickEventArgs, ItemDirective, ItemsDirective, ToolbarComponent } from '@syncfusion/ej2-react-navigations';
import { ChangeEventArgs, CheckBox } from '@syncfusion/ej2-buttons';
import { MenuEventArgs, SplitButton, SplitButtonComponent } from '@syncfusion/ej2-react-splitbuttons';
import { DropDownListComponent } from '@syncfusion/ej2-react-dropdowns';

function App() {
  let signature: SignatureComponent;
  let disabledTemplate: CheckBox = new CheckBox({ label: 'Disabled', checked: false, change: change });
  function change(args: ChangeEventArgs): void {
      let signature: Signature = getComponent(document.getElementById('signature'), 'signature');
      signature.disabled = args.checked;
  }

  function onCreated(): void {
      let strokeColor: ColorPicker = getComponent(document.getElementById('stroke-color'), 'colorpicker');
      let bgColor: ColorPicker = getComponent(document.getElementById('bg-color'), 'colorpicker');
      addClass([strokeColor.element.nextElementSibling.querySelector('.e-selected-color')], 'e-sign-icons');
      addClass([bgColor.element.nextElementSibling.querySelector('.e-selected-color')], 'e-sign-icons');
      document.getElementById('save-option').addEventListener('click', saveBtnClick);
      clearButton();
      let toolbarlItems: NodeListOf<Element> = document.querySelectorAll('.e-toolbar .e-toolbar-items .e-toolbar-item .e-tbar-btn.e-tbtn-txt');
      for (var i = 0; i < toolbarlItems.length; i++) {
          if (toolbarlItems[i].children[0].classList.contains('e-undo')) {
              let undoButton: Button = getComponent(toolbarlItems[i] as HTMLElement, 'btn');
              undoButton.disabled = true;
          }
          if (toolbarlItems[i].children[0].classList.contains('e-redo')) {
              let redoButton: Button = getComponent(toolbarlItems[i] as HTMLElement, 'btn');
              redoButton.disabled = true;
          }
      }
  }

  function onClicked(args: ClickEventArgs): void {
      let signature: Signature = getComponent(document.getElementById('signature'), 'signature');
      let saveBtn: SplitButton = getComponent(document.getElementById("save-option"), 'split-btn');
      if (signature.disabled && args.item.tooltipText != 'Disabled') {
          return;
      }
      switch (args.item.tooltipText) {
          case 'Undo (Ctrl + Z)':
              if (signature.canUndo()) {
                  signature.undo();
                  updateUndoRedo();
                  updateSaveBtn();
              }
              break;
          case 'Redo (Ctrl + Y)':
              if (signature.canRedo()) {
                  signature.redo();
                  updateUndoRedo();
                  updateSaveBtn();
              }
              break;
          case 'Clear':
              signature.clear();
              if (signature.isEmpty()) {
                  clearButton();
                  saveBtn.disabled = true;
              }
              break;
      }
  }

  function onChange() {
      let signature: Signature = getComponent(document.getElementById('signature'), 'signature');
      let saveBtn: SplitButton = getComponent(document.getElementById("save-option"), 'split-btn');
      if (!signature.isEmpty()) {
          clearButton();
          saveBtn.disabled = false;
      }
      updateUndoRedo();
  }

  function saveBtnClick(): void {
      let signature: Signature = getComponent(document.getElementById("signature"), 'signature');
      signature.save();
  }

  function clearButton() {
      let signature: Signature = getComponent(document.getElementById('signature'), 'signature');
      let tlItems: NodeListOf<Element> = document.querySelectorAll('.e-toolbar .e-toolbar-items .e-toolbar-item .e-tbar-btn.e-tbtn-txt');
      for (var i = 0; i < tlItems.length; i++) {
          if (tlItems[i].children[0].classList.contains('e-clear')) {
              let clrBtn: Button = getComponent(tlItems[i] as HTMLElement, 'btn');
              if (signature.isEmpty()) {
                  clrBtn.disabled = true;
              } else {
                  clrBtn.disabled = false;
              }
          }
      }
  }

  function updateSaveBtn() {
      let signature: Signature = getComponent(document.getElementById('signature'), 'signature');
      let saveBtn: SplitButton = getComponent(document.getElementById("save-option"), 'split-btn');
      if (signature.isEmpty()) {
          saveBtn.disabled = true;
      } else {
          saveBtn.disabled = false;
      }
  }

  function updateUndoRedo() {
      let signature: Signature = getComponent(document.getElementById('signature'), 'signature');
      let undoButton: Button; let redoButton: Button
      let tlItems: NodeListOf<Element> = document.querySelectorAll('.e-toolbar .e-toolbar-items .e-toolbar-item .e-tbar-btn.e-tbtn-txt');
      for (var i = 0; i < tlItems.length; i++) {
          if (tlItems[i].children[0].classList.contains('e-undo')) {
              undoButton = getComponent(tlItems[i] as HTMLElement, 'btn');
          }
          if (tlItems[i].children[0].classList.contains('e-redo')) {
              redoButton = getComponent(tlItems[i] as HTMLElement, 'btn');
          }
      }
      if (signature.canUndo()) {
          undoButton.disabled = false;
      } else {
          undoButton.disabled = true;
      }
      if (signature.canRedo()) {
          redoButton.disabled = false;
      } else {
          redoButton.disabled = true;
      }
  }

  function saveTemplate() {
      let items: { text: string; }[];
      items = [
          {
              text: 'Png'
          },
          {
              text: 'Jpeg'
          },
          {
              text: 'Svg'
          }
      ];

      function onSelect(args: MenuEventArgs): void {
          let signature: Signature = getComponent(document.getElementById('signature'), 'signature');
          signature.save(args.item.text as SignatureFileType, 'Signature');
      }

      return (<div >
          <SplitButtonComponent content="Save" id="save-option" items={items} iconCss='e-sign-icons e-save' select={onSelect} disabled={true} />
      </div>);
  }

  function strokeColorTemplate() {
      let presets: any;
      presets = {
          'custom': ['#000000', '#e91e63', '#9c27b0', '#673ab7', '#2196f3', '#03a9f4', '#00bcd4',
              '#009688', '#8bc34a', '#cddc39', '#ffeb3b', '#ffc107']
      };

      function tileRender(args: PaletteTileEventArgs): void {
          args.element.classList.add('e-circle-palette');
          args.element.appendChild(createElement('span', { className: 'e-circle-selection' }));
      }

      function strokeColorChanged(args: ColorPickerEventArgs): void {
          let signature: Signature = getComponent(document.getElementById('signature'), 'signature');
          let strokeColor: ColorPicker = getComponent(document.getElementById('stroke-color'), 'colorpicker');
          if (signature.disabled) {
              return;
          }
          let selElem: HTMLElement = strokeColor.element.nextElementSibling.querySelector('.e-selected-color') as HTMLElement;
          selElem.style.borderBottomColor = args.currentValue.rgba;
          signature.strokeColor = args.currentValue.rgba;
      }

      return (<div >
          <ColorPickerComponent id="stroke-color" mode='Palette' cssClass='e-stroke-color' modeSwitcher={false} showButtons={false} columns={4} presetColors={presets} beforeTileRender={tileRender} change={strokeColorChanged}></ColorPickerComponent>
      </div>);
  }
  
  function bgColorTemplate() {
      let presets: any;
      presets = {
          'custom': ['#ffffff', '#f44336', '#e91e63', '#9c27b0', '#673ab7', '#2196f3', '#03a9f4', '#00bcd4',
              '#009688', '#8bc34a', '#cddc39', '#ffeb3b']
      };


      function beforeTileRender(args: PaletteTileEventArgs): void {
          args.element.classList.add('e-circle-palette');
          args.element.appendChild(createElement('span', { className: 'e-circle-selection' }));

      }

      function bgColorChanged(args: ColorPickerEventArgs): void {
          let signature: Signature = getComponent(document.getElementById('signature'), 'signature');
          let bgColor: ColorPicker = getComponent(document.getElementById('bg-color'), 'colorpicker');
          if (signature.disabled) {
              return;
          }
          let selElem: HTMLElement = bgColor.element.nextElementSibling.querySelector('.e-selected-color') as HTMLElement;
          signature.backgroundColor = args.currentValue.rgba;
          selElem.style.borderBottomColor = args.currentValue.rgba;
      }

      return (<div >
          <ColorPickerComponent id="bg-color" noColor={true} mode='Palette' cssClass='e-bg-color' modeSwitcher={false} showButtons={false} columns={4} presetColors={presets} beforeTileRender={beforeTileRender} change={bgColorChanged}></ColorPickerComponent>
      </div>);
  }

  function strokeWidthTemplate() {
      let data: any = [1, 2, 3, 4, 5];
      let value: any = 2;


      function strokeWidthChanged(args: any): void {
          let signature: Signature = getComponent(document.getElementById('signature'), 'signature');
          signature.maxStrokeWidth = args.value;
      }

      return (<div >
          <DropDownListComponent id="ddlelement" dataSource={data} value={value} width="60" change={strokeWidthChanged} />
      </div>);
  }

  return (
      <div className='control-pane'>
          <div className="col-lg-12 control-section">
              <div id="signature-toolbar-control">
                  <ToolbarComponent id='toolbar' created={onCreated} clicked={onClicked}>
                      <ItemsDirective>
                          <ItemDirective text='Undo' prefixIcon='e-icons e-undo' tooltipText='Undo (Ctrl + Z)' />
                          <ItemDirective text='Redo' prefixIcon='e-icons e-redo' tooltipText='Redo (Ctrl + Y)' />
                          <ItemDirective type='Separator' />
                          <ItemDirective tooltipText='Save (Ctrl + S)' type='Button' template={saveTemplate} />
                          <ItemDirective type='Separator' />
                          <ItemDirective tooltipText='Stroke Color' template={strokeColorTemplate} />
                          <ItemDirective type='Separator' />
                          <ItemDirective tooltipText='Background Color' template={bgColorTemplate} />
                          <ItemDirective type='Separator' />
                          <ItemDirective tooltipText='Stroke Width' template={strokeWidthTemplate} />
                          <ItemDirective type='Separator' />
                          <ItemDirective text='Clear' prefixIcon='e-sign-icons e-clear' tooltipText='Clear' />
                          <ItemDirective tooltipText='Disabled' type='Input' template={disabledTemplate} align='Right' />
                      </ItemsDirective>
                  </ToolbarComponent>
                  <div id="signature-control">
                      <SignatureComponent maxStrokeWidth={2} id="signature" change={onChange}></SignatureComponent>
                  </div>
              </div>
          </div>
      </div>
  )
}
export default App;
ReactDOM.render(<App />, document.getElementById('element'));