Privacy Policy and Cookies

By continuing to use our site, you agree to our Privacy Policy and our use of cookies to understand how you use our site, and to improve your experience. Learn More.
I Agree.

Multi-Record Editing in SmartClient

Last modified date

Multi-Record Editing in SmartClient

Multi-record editing is often a complex process involving tracking and managing pending edits across multiple records.

It encompasses several data management concerns. They include temporarily storing and merging edits server-side, ensuring optimal performance, addressing potential collisions, and even applying distinct styling for edited values. It also requires cleaning up any temporary storage used on the server. 

By leveraging the extensive suite of SmartClient components, multi-record editing, which is often a convoluted task, becomes significantly more manageable and efficient.

Let’s dive deep into its incredible features and how to set it up!

Complexity and performance concerns with multi-record editing

In web applications, updating multiple records at once carries a degree of complexity and potential performance bottlenecks. The common approach is to store temporary edits on the server and merge them back with the original values.

This approach, while commonplace, introduces several complications. For instance, the merging process can lead to errors or conflicts in data. Moreover, constant server communication will surely increase network latency. Find out more in this web application optimization article.

In SmartClient, you can manage pending edits exclusively on the client-side. This approach eliminates the overhead associated with server-side temporary storage.

Setting up multi-record editing in SmartClient

Create the DataSource

We will use one of the built-in DataSources available on SmartClient – employeeDS.

<DataSource isSampleDS="true" ID="employees" serverType="sql" tableName="employeeTable" recordName="employee"
    testFileName="/examples/shared/ds/test_data/employees.data.xml" titleField="Name">
    <fields>
        <field name="Name" title="Name" type="text" length="128" />
        <field name="Job" title="Title" type="text" length="128" />
        <field name="EmployeeType" title="Employee Type" type="text" length="40" />
        <field name="EmployeeStatus" title="Status" type="text" length="40" />
        <field name="Salary" title="Salary" type="float" />
        <field name="MaritalStatus" title="Marital Status" type="text" length="10">
            <valueMap>
                <value>married</value>
                <value>single</value>
            </valueMap>
        </field>
    </fields>
</DataSource>

Create the UI for multi-record editing

First, start by creating a ListGrid for the UI, and then bind the DataSource to that particular UI. We will set canEdit: true and autoSaveEdits: false. This way, we can edit multiple records and save them all at once.

isc.ListGrid.create({
    ID: "employeeList",
    width: '100%',
    height: 224,
    dataSource: savedsearchDS,
    autoFetchData: true,
    canEdit: true,
    editEvent: "doubleClick",
    autoSaveEdits: false,
    fields: [
        { name: 'Name', title: 'Name' },
        { name: 'Job', title: 'Title' },
        { name: 'EmployeeType', title: 'Employee Type' },
        { name: 'EmployeeStatus', title: 'Status' },
        { name: 'Salary', title: 'Salary' },
        { name: 'MaritalStatus', title: 'Marital Status' }
    ]
});

With the ListGrid created, we’ll add 3 buttons to the UI: “Save”, “Edit New”, and “Discard”. SmartClient makes this entire process easy with methods available for each of these buttons.

isc.HLayout.create({
    ID: "ButtonUI",
    width: 750,
    height: 50,
    layoutMargin: 15,
    membersMargin: 10,
    members: [
        isc.IButton.create({
            ID: "editNewButton",
            title: "Edit New",
            click: "employeeList.startEditingNew()"
        }),
        isc.IButton.create({
            ID: "saveButton",
            title: "Save",
            click: "employeeList.saveAllEdits()"
        }),
        isc.IButton.create({
            ID: "discardAllButton",
            title: "Discard",
            click: "employeeList.discardAllEdits()"
        })
    ]
});

The “Save” and “Discard” buttons let you store bulk edits all at once, or just discard the edits if you don’t want them.

The grid forwards all the changes as a unified HTTP request, which allows them to be committed as a single transaction. This is the default setting if you have the SmartClient server. SmartClient styles the bulk edits differently from the rest of the records. You can configure it using pendingBaseStyle.

The last button – “Edit New” – lets you add a new record to the grid.

UI for multi-record editing
UI for multi-record editing

Advanced usage: Extend editing UI

SmartClient offers the flexibility to extend editing beyond just the grid.

Imagine a scenario where you view data within a grid and then edit it in a separate DynamicForm interface. Sometimes, this could help with complex fields, providing on-screen tips, or just a preference for a better-segmented approach. With this UI design, you get a richer editing experience.

We will create a new ListGrid that shows how you could use a grid with autoSaveEdits:false and also canEdit:false. This grid will work as a tracker and manager of unsaved edits in other interfaces.

Then we’ll add a click function that will enable us to edit the record in a DynamicForm.

isc.ListGrid.create({
    ID: "trackerGrid",
    height: 224,
    dataSource: savedsearchDS,
    autoFetchData: true,
    autoSaveEdits: false,
    canEdit: false,
    autoDraw: false,
    fields: [
        { name: 'Name', title: 'Name' },
        { name: 'Job', title: 'Title' },
        { name: 'EmployeeType', title: 'Employee Type' },
        { name: 'EmployeeStatus', title: 'Status' },
        { name: 'Salary', title: 'Salary' },
        { name: 'MaritalStatus', title: 'Marital Status' }
    ],
    recordDoubleClick: "editForm.editSelectedData(trackerGrid)"
});

We’ll add the DynamicForm that will provide an interface for editing the grid. We also want to add 3 buttons: one to queue up bulk edits in the grid, another to save them, and a last one to discard them. 

isc.DynamicForm.create({
    ID: "editForm",
    autoDraw: false,
    itemKeyPress: function (item, form, keyName) {
        if (keyName === 'Enter') {
            var values = editForm.getValues();
            var selectedRecord = trackerGrid.getSelectedRecord();
            var rowNum = trackerGrid.getRecordIndex(selectedRecord);
            trackerGrid.setEditValues(rowNum, values);
            editForm.clearValues();
        }
    },
    fields: [
        { name: 'Name', title: 'Name' },
        { name: 'Job', title: 'Title' },
        { name: 'EmployeeType', title: 'Employee Type', valueMap: ['part time', 'full time', 'contract'] },
        { name: 'EmployeeStatus', type: 'radioGroup', title: 'Status', valueMap: ['LOA', 'active'] },
        { name: 'Salary', title: 'Salary' },
        { name: 'MaritalStatus', title: 'Marital Status', valueMap: ['married', 'single'] }
    ]
});

isc.IButton.create({
    ID: "queueEditButton",
    title: 'Queue Edit',
    autoDraw: false,
    click: function () {
        var values = editForm.getValues();
        var selectedRecord = trackerGrid.getSelectedRecord();
        var rowNum = trackerGrid.getRecordIndex(selectedRecord);
        trackerGrid.setEditValues(rowNum, values);
        editForm.clearValues();
    }
});

isc.IButton.create({
    ID: "saveAllButton",
    title: 'Save All Edits',
    autoDraw: false,
    click: function () {
        trackerGrid.saveAllEdits();
    }
});

isc.IButton.create({
    ID: "discardAllButton",
    title: 'discardAllButton',
    autoDraw: false,
    click: function () {
        trackerGrid.discardAllEdits();
        editForm.clearValues();
    }
});

In this configuration:

  • The grid has canEdit set to false, which disables direct editing.
  • When you select a grid, the recordClick method captures the event, and loads the selected record into DynamicForm.
  • Within the DynamicForm, you can add an edit using the itemKeyPress method or “Queue Edit” button. This, in turn, uses the setEditValues method to update the grid with the new value, marking it as a pending edit.
  • A “Save All Edits” button that allows you to batch edits together and mass update them at once.

So, while the updates happen outside the grid, it remains the central manager for tracking and visually presential changes.

queue bulk edits at once
UI for seperate UI editing

In the image, the cells with the bulk edits are styled differently from the original values. We’ve queued up the bulk edits so we can save them all at once.

How SmartClient handles concurrent changes

The fluidity of SmartClient’s editing capabilities also extends to handling concurrent data changes. In dynamic environments with multiple users, the possibility of two users editing the same record is certain. SmartClient provides a robust set of tools to detect and manage these changes.

SmartClient allows you to implement systems that alert you to changes made by others during edits. This ensures that users are always aware of the latest data state and can make informed decisions about their edits.

To know how SmartClient does this, check out Concurrent Change Management in SmartClient.

Conclusion

The importance of multi-record editing is undeniable. While the process is complex, SmartClient makes it so much simpler. It drastically reduces the overhead, offering an optimized, flexible, and efficient editing experience.

SmartClient can seamlessly accommodate any kind of editing interface. There isn’t even a strict necessity to showcase the grid. You can reduce their primary function to merely track changes, and display issues for review at the end.

SmartClient ensures limitless productivity and efficiency whether you’re editing in a grid, separate UI, or handling concurrent edits.

Alex Fashakin