JavaScript/jQuery Splitter - Getting Started

jQuery
NOTE
Before you start the tutorial, ensure DevExtreme is installed in your application.
Angular
NOTE
Before you start the tutorial, ensure DevExtreme is installed in your application.
Vue
NOTE
Before you start the tutorial, ensure DevExtreme is installed in your application.
React
NOTE
Before you start the tutorial, ensure DevExtreme is installed in your application.

Splitter is a UI component designed to split a page layout into multiple panes.

This tutorial shows how to add Splitter to the page and configure the component's core settings. For example, you can create the following page layout:

Each section in this tutorial describes a single configuration step. You can also find the full source code in the following GitHub repository:

View on GitHub

Build a Layout

In this tutorial, the Splitter takes up only a part of the page. To achieve this goal, set the component's width and height properties to 500px and 400px respectively.

NOTE
If you want to split the entire page, place a Splitter in the <body> tag and set the width and height options to 100% for both the Splitter and the <html> tag.

A Splitter can arrange its items either horizontally (default) or vertically.

You can use two options to specify Splitter item content:

  • items
    Specifies pane content directly in code. This option is used in this tutorial.

  • dataSource
    Obtains pane content stored separately from the main code.

Each pane can hold another Splitter. Each nested Splitter uses the same configuration properties as its parent.

Once you set up pane layout, the Splitter displays separator bars between panes. You can specify the width of these bars in pixels.

jQuery
index.js
index.html
$(() => {
    $("#splitter").dxSplitter({
        width: 500,
        height: 400,
        separatorSize: 5,
        items: [
            { },
            {
                splitter: {
                    separatorSize: 5,
                    orientation: "vertical",
                    items: [
                        { },
                        { },
                        { }
                    ]
                }
            }
        ]
    });
});
<div id="container">
    <div id="splitter"></div>
</div>
Angular
app.component.html
app.module.ts
<container>
    <dx-splitter
        [width]="500"
        [height]="400"
        [separatorSize]="5"
    >
        <dxi-item></dxi-item>
        <dxi-item>
            <dx-splitter orientation="vertical" [separatorSize]="5">
                <dxi-item></dxi-item>
                <dxi-item></dxi-item>
                <dxi-item></dxi-item>
            </dx-splitter>
        </dxi-item>
        </dx-splitter>
</container>
import { BrowserModule } from '@angular/platform-browser'; 
import { NgModule } from '@angular/core'; 
import { AppComponent } from './app.component'; 
import { DxSplitterModule } from 'devextreme-angular'; 

@NgModule({ 
    declarations: [ 
        AppComponent 
    ], 
    imports: [ 
        BrowserModule, 
        DxSplitterModule
    ], 
    providers: [ ], 
    bootstrap: [AppComponent] 
}) 
export class AppModule { }
Vue
App.vue
<template>
    <container>
          <DxSplitter :width="500" :height="400" :separator-size="5">
            <DxItem />
            <DxItem>
            <DxSplitter orientation="vertical" :separator-size="5">
                <DxItem />
                <DxItem />
                <DxItem />
            </DxSplitter>
            </DxItem>
        </DxSplitter>
    </container>
</template>

<script setup>  
    import 'devextreme/dist/css/dx.light.css';
    import { DxSplitter, DxItem } from 'devextreme-vue/splitter';
</script>
React
App.js
import React from 'react';
import Splitter, { Item } from 'devextreme-react/splitter';
import 'devextreme/dist/css/dx.light.css';

const App = () => (
<React.Fragment>
    <container>
        <Splitter
            width={500}
            height={400}
            separatorSize={5}
        >
            <Item />
            <Item>
                <Splitter orientation="vertical" separatorSize={5}>
                    <Item />
                    <Item />
                    <Item />
                </Splitter>
            </Item>
        </Splitter>
    </container>
</React.Fragment>
);

export default App;

Configure Panes

The following options specify the Splitter state and available user interaction capabilities:

  • resizable (default: true)
    If true, a handle appears on the pane separator. Drag the handle to adjust pane size.

  • collapsible (default: false)
    If true, an arrow appears on the handle. Click the arrow to collapse/expand the pane.

  • collapsed (default: false)
    Specifies whether the pane is collapsed.

Use the following properties to specify pane size. Note that all these properties depend on Splitter orientation. They specify width in 'horizontal' orientation and height in 'vertical' orientation.

  • size
    Pane width/height.

  • minSize
    Minimum width/height for a resizable pane.

  • maxSize
    Maximum width/height for a resizable pane.

  • collapsedSize
    Pane width/height in the collapsed state.

This tutorial explicitly specifies the following properties: size, minSize, maxSize, and collapsible. All panes are resizable, since this is a default behavior.

jQuery
index.js
$(() => {
    $("#splitter").dxSplitter({
        // ...
        items: [
            {
                size: '285px',
            },
            {
                splitter: {
                    // ...
                    items: [
                        { 
                           size: '80%', 
                        },
                        { 
                            collapsible: true,
                            minSize: '40px',
                        },
                        { 
                            collapsible: true,
                            maxSize: '30px',
                        }
                    ]
                }
            }
        ]
    });
});
Angular
app.component.html
<container>
    <dx-splitter ... >
        <dxi-item size="285px"></dxi-item>
        <dxi-item>
            <dx-splitter ...>
                <dxi-item size="80%"></dxi-item>
                <dxi-item [collapsible]="true" minSize="40px"></dxi-item>
                <dxi-item
                    [collapsible]="true"
                    maxSize="30px"
                ></dxi-item>
            </dx-splitter>
        </dxi-item>
        </dx-splitter>
</container>
Vue
App.vue
<template>
    <container>
          <DxSplitter ... >
            <DxItem size="285px" />
            <DxItem>
            <DxSplitter ... >
                <DxItem size="80%" />
                <DxItem :collapsible="true" minSize="40px" />
                <DxItem 
                    :collapsible="true"
                    maxSize="30px"
                />
            </DxSplitter>
            </DxItem>
        </DxSplitter>
    </container>
</template>

<script setup>  
    // ...
</script>
React
App.js
import React from 'react';
import Splitter, { Item } from 'devextreme-react/splitter';
import 'devextreme/dist/css/dx.light.css';

const App = () => (
<React.Fragment>
    <container>
        <Splitter ... >
            <Item size="285px" />
            <Item>
                <Splitter orientation="vertical" separatorSize={5}>
                    <Item size="80%" />
                    <Item collapsible={true} minSize="40px" />
                    <Item collapsible={true} maxSize="30px"/>
                </Splitter>
            </Item>
        </Splitter>
    </container>
</React.Fragment>
);

export default App;

Fill Panes with Content

Splitter panes can include different content types, from simple HTML markup to components. You can declare HTML markup inside the item tag or use the following properties to populate panes with content:

  • text
    Specifies the text displayed in the pane.

  • itemTemplate
    Specifies a custom template for all panes.

  • template
    Specifies a custom template for an individual pane.

This tutorial uses templates to define components inside panes:

  • The first pane includes a Form component.
  • All changes made in Form are recorded in the second pane.
  • The third pane contains a button, and users can click it to erase the output in the second pane and reset the Form.
  • The last pane demonstrates the use of the text property.
jQuery
index.js
$(() => {
    const employee = {
        ID: 1,
        FirstName: 'John',
        LastName: 'Heart',
        Position: 'CEO',
        BirthDate: '1964/03/16',
        HireDate: '1995/01/15',
        Notes:
            'John has been in the Audio/Video industry since 1990. He has led DevAv as its CEO since 2003.\r\n\r\nWhen not working hard as the CEO, John loves to golf and bowl. He once bowled a perfect game of 300.',
        Address: '351 S Hill St., Los Angeles, CA',
        Phone: '360-684-1334',
        Email: 'jheart@dx-email.com',
    };
    const $output = $('<div>Output:</div>');
    $("#splitter").dxSplitter({
        // ...
        items: [
            { 
                // ...
                template() {
                    const $form = $("<div id='form'/>");
                    $form.dxForm({
                        formData: employee,
                        onFieldDataChanged(e) {
                            $output.append(`<div>${e.value}</div>`);
                        },
                    });
                    return $form;
                },
            },
            {
                splitter: {
                    // ...
                    items: [
                        { 
                            // ...
                            template() {
                                return $output;
                            },
                        },
                        { 
                            // ...
                            template() {
                                const $button = $('<div/>');
                                $button.dxButton({
                                    text: 'Clear all entries',
                                    onClick() {
                                        $('#form').dxForm('reset');
                                        $output.empty();
                                        $output.append('<div>Output:</div>');
                                    },
                                });
                                return $button;
                            },
                        },
                        {
                            // ...
                            text: 'All rights are reserved ©',
                        }
                    ]
                }
            }
        ]
    });
});
Angular
app.component.html
app.component.ts
app.module.ts
<container>
    <dx-splitter ... >
        <dxi-item ... >
            <dx-form
                id="form"
                [formData]="employee"
                (onFieldDataChanged)="onFieldDataChanged($event)"
            ></dx-form>
        </dxi-item>
        <dxi-item>
            <dx-splitter ... >
                <dxi-item ... >
                    <div *ngFor="let item of output">{{ item }}</div>
                </dxi-item>
                <dxi-item ... >
                    <dx-button
                        text="Clear all entries"
                        (onClick)="resetFormAndOutput()"
                    ></dx-button>
                </dxi-item>
                <dxi-item ...
                    text="All rights are reserved ©"
                ></dxi-item>
            </dx-splitter>
        </dxi-item>
        </dx-splitter>
</container>
import { Component } from '@angular/core';

@Component({
    selector: 'app-root',
    templateUrl: './app.component.html',
    styleUrls: ['./app.component.scss'],
})

export class AppComponent {
    initialEmployee = {
        ID: 1,
        FirstName: 'John',
        LastName: 'Heart',
        Position: 'CEO',
        BirthDate: '1964/03/16',
        HireDate: '1995/01/15',
        Notes: 'John has been in the Audio/Video industry since 1990. He has led DevAv as its CEO since 2003.\r\n\r\nWhen not working hard as the CEO, John loves to golf and bowl. He once bowled a perfect game of 300.',
        Address: '351 S Hill St., Los Angeles, CA',
        Phone: '360-684-1334',
        Email: 'jheart@dx-email.com',
    };

    employee = { ...this.initialEmployee };

    output: string[] = ['Output:'];

    suppressFieldChangeEvent = false;

    onFieldDataChanged(e: any) {
        if (!this.suppressFieldChangeEvent) {
            this.output.push(e.value);
        }
    }

    resetFormAndOutput() {
        this.suppressFieldChangeEvent = true;
        this.employee = { ...this.initialEmployee };
        this.output = ['Output:'];
        setTimeout(() => {
            this.suppressFieldChangeEvent = false;
        }, 0);
    }
}
import { BrowserModule } from '@angular/platform-browser'; 
import { NgModule } from '@angular/core'; 
import { AppComponent } from './app.component'; 
import { DxSplitterModule, DxFormModule, DxButtonModule } from 'devextreme-angular'; 

@NgModule({ 
    declarations: [ 
        AppComponent 
    ], 
    imports: [ 
        BrowserModule, 
        DxSplitterModule,
        DxFormModule,
        DxButtonModule
    ], 
    providers: [ ], 
    bootstrap: [AppComponent] 
}) 
export class AppModule { }
Vue
App.vue
<template>
    <container>
          <DxSplitter ... >
            <DxItem ... >
                <DxForm
                    :form-data="employee"
                    @field-data-changed="onFieldDataChanged"
                />
            </DxItem>
            <DxItem>
            <DxSplitter orientation="vertical" :separator-size="5">
                <DxItem ... >
                    <div>
                        <div v-for="(item, index) in output" :key="index">{{ item }}</div>
                    </div>
                </DxItem>
                <DxItem ... >
                    <DxButton text="Clear all entries" @click="resetFormAndOutput"></DxButton>
                </DxItem>
                <DxItem ... 
                    text="All rights are reserved ©" 
                />
            </DxSplitter>
            </DxItem>
        </DxSplitter>
    </container>
</template>

<script setup>  
    import { ref } from 'vue';
    import 'devextreme/dist/css/dx.light.css';
    import DxForm from 'devextreme-vue/form';
    import DxButton from 'devextreme-vue/button';
    import { DxSplitter, DxItem } from 'devextreme-vue/splitter';

    const initialEmployee = {
        ID: 1,
        FirstName: 'John',
        LastName: 'Heart',
        Position: 'CEO',
        BirthDate: '1964/03/16',
        HireDate: '1995/01/15',
        Notes: 'John has been in the Audio/Video industry since 1990. He has led DevAv as its CEO since 2003.\r\n\r\nWhen not working hard as the CEO, John loves to golf and bowl. He once bowled a perfect game of 300.',
        Address: '351 S Hill St., Los Angeles, CA',
        Phone: '360-684-1334',
        Email: 'jheart@dx-email.com',
    };

    let employee = ref({ ...initialEmployee });
    const output = ref(['Output:']);
    let suppressFieldChangeEvent = ref(false);

    const onFieldDataChanged = (e) => {
        if (!suppressFieldChangeEvent.value) {
            output.value.push(e.value);
        }
    };

    const resetFormAndOutput = () => {
        suppressFieldChangeEvent.value = true;
        employee.value = { ...initialEmployee };
        output.value = ['Output:'];
        setTimeout(() => {
            suppressFieldChangeEvent.value = false;
        }, 0);
    };
</script>
React
App.js
import 'devextreme/dist/css/dx.light.css';
import { useState } from 'react';
import Form from 'devextreme-react/form';
import Button from 'devextreme-react/button';
import Splitter, { Item } from 'devextreme-react/splitter';

const App = () => {
    const initialEmployee = {
        ID: 1,
        FirstName: 'John',
        LastName: 'Heart',
        Position: 'CEO',
        BirthDate: '1964/03/16',
        HireDate: '1995/01/15',
        Notes: 'John has been in the Audio/Video industry since 1990. He has led DevAv as its CEO since 2003.\r\n\r\nWhen not working hard as the CEO, John loves to golf and bowl. He once bowled a perfect game of 300.',
        Address: '351 S Hill St., Los Angeles, CA',
        Phone: '360-684-1334',
        Email: 'jheart@dx-email.com',
    };

    const [employee, setEmployee] = useState({ ...initialEmployee });
    const [output, setOutput] = useState(['Output:']);
    const [suppressFieldChangeEvent, setSuppressFieldChangeEvent] = useState(false);

    const onFieldDataChanged = (e) => {
        if (!suppressFieldChangeEvent) {
            setOutput((prevOutput) => [...prevOutput, e.value]);
        }
    };

    const resetFormAndOutput = () => {
        setSuppressFieldChangeEvent(true);
        setEmployee({ ...initialEmployee });
        setOutput(['Output:']);
        setTimeout(() => {
            setSuppressFieldChangeEvent(false);
        }, 0);
    };

    return (
        <Splitter ... >
        <Item ... >
            <Form
                formData={employee}
                onFieldDataChanged={onFieldDataChanged}
            />
        </Item>
        <Item>
            <Splitter ... >
            <Item ... >
                <div>
                    {output.map((item, index) => (
                        <div key={index}>{item}</div>
                    ))}
                </div>
            </Item>
            <Item ... >
                <Button
                    text="Clear all entries"
                    onClick={resetFormAndOutput}
                />
            </Item>
            <Item ...
                text="All rights are reserved ©" 
            />
            </Splitter>
        </Item>
        </Splitter>
    );
};

export default App;