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.
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'));
<!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>
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'));