public interface Editing
Enabling editing
Editing is enabled when
canEdit
is true
.
When enabled, the user can begin editing via the editEvent
, typically click or
double-click. Editing can also be triggered programmatically by a call to startEditing()
or startEditingNew()
.
New record creation
By default, editing is restricted to existing records. Setting listEndEditAction
to "next"
allows the user to create new records by simply navigating off the end of the dataset with the
keyboard. Editing of new records can also be initiated with ListGrid.startEditingNew
, for
example, from a button outside the grid. See the Unsaved Records Overview
for special concerns when
dealing with unsaved records.
Saving changes
Saving of changes is triggered
automatically when the user navigates out of the row or cell being edited (based on saveByCell
) or when the user ends
editing. For a "mass update" interface, automatic saving of changes can be disabled entirely
via autoSaveEdits:false
, in
which case a manual call to saveEdits()
or saveAllEdits()
is required to trigger saving.
If a grid has no DataSource, saving means that the
properties of the ListGridRecord
s in grid.data
are directly changed.
For a
grid with a DataSource, saving will be accomplished by using DataSource "update" operations for
existing records, and DataSource "add" operations for new records. If multiple records have
been edited and saveAllEdits()
is called, request queuing
will be
automatically used to enable all edits to be saved in one HTTP turnaround (if using the Smart
GWT Server).
By default, a grid will send only updated fields and primaryKey fields as part
of data
so that the server can discern which
fields the user actually changed. However, the grid always includes the original field values
in the dsRequest as oldValues
.
Note
that although it is possible to load DataSource data without actually declaring a primaryKey field
, a primaryKey must be
declared for editing and saving. The values of primaryKey fields is how Smart GWT identifies
the changed record to the server.
Validation
Any time saving is attempted,
validation is automatically triggered. Values entered by the user will be checked against the
validators
and the validators
. Any invalid values abort an
attempted save.
Similar to editing and saving, validation can be done on row transitions or
on cell transitions by setting validateByCell
, or can be disabled
entirely via neverValidate:true
.
Editability of cells
Editors will either be shown for the
complete row or for a single cell based on editByCell,editByCell
. Whether a cell can be edited can be controlled on a per field basis by
setting field.canEdit
, or on
a per-record basis by setting recordEditProperty
on a record
, or can be controlled on an arbitrary,
programmatic basis via an override of ListGrid.canEditCell
.
Cells which are not editable just display the cell's current value.
Keyboard Navigation
Full keyboard navigation is supported by default, including Tab and Shift-Tab to navigate between cells in a row, and Up Arrow and Down Arrow to traverse rows. Several properties on both grids and fields, all named *EditAction, control navigation behavior of certain keys (eg Enter).
You can use startEditing(rowNum, colNum)
to programmatically move editing to a particular
cell, for example, during a field.changed()
event.
editValues (unsaved changes)
The term "editValues" means changes that the user has made to the dataset which have not been saved. The grid manages and stores editValues separately from the data itself in order to allow the user to revert to original values, and in order to enable to grid to send only updated fields to the server.
Because editValues are stored separately, if you directly access the dataset (eg via
grid.getData().get()
) you will see the records without the user's unsaved changes.
Many APIs exist for retrieving and managing editValues (search for editValue). For the common
case of needing to access the record-as-edited, you can call grid.getEditedRecord(rowNum)
.
When accessing and manipulating edited data, you should think carefully about whether you want to be working with the original data or with the edited version. Values entered by the user may not have been validated yet, or may have failed validation, hence you may find a String value in a field of type "date" or "int", which could cause naive formatters or totaling functions to crash.
Setting editValues via APIs such as ListGrid.setEditValue
is fully
equivalent to the user making changes to data via the editing UI. If you also allow
editing external to the grid, setting editValues is one way to combine changes from external
editors into the grid's edits, so that you can do a single save.
Customizing Cell Editors
When a cell is being edited, the editor displayed in the cell will be a FormItem
. The editor type for the cell will be
determined by ListGrid.getEditorType
based on the specified editorType
or data type
for the field in question.
You can customize the editor by setting editorProperties
to a set
of properties that is valid for that FormItem type. Custom FormItem classes are also allowed,
for example, you may use icons
to create an icon that launches a separate Dialog
in
order to provide an arbitrary interface that allows the user to select the value for a field.
Events
Editing triggers several events which you can provide handlers for in
order to customize editing behavior. Some of the most popular are field.change()
, field.changed()
for detecting changes
made by the user, ListGrid.cellChanged
for detecting changes that have been successfully saved, and editorEnter
and editorExit()
for detecting user
navigation during editing.
ListGridField.setEditorType()
can be used to
customize the editors shown for each field, including providing FormItem-specific event
handlers. However, ListGrid-provided event APIs should be used wherever possible (for example,
use EditorEnterEvent
rather than FocusEvent
). If, in a FormItem
event handler, you need access to the ListGrid, you can either declare the event handler as a
Java "inner class" in a scope where the ListGrid is available as a final variable, or you can
use event.getItem().getContainerWidget()
. Note the ListGrid APIs getEditRow()
and getEditCol()
indicate what cell is being
edited.
For more dynamic editor customization, include changing the type of editor used on
a per-row basis, use setEditorCustomizer
.
NOTE: with both APIs, in effect several FormItems are
generated from the customized FormItem you provide - see the docs for setEditorType
for special coding
patterns that apply in this case.
Binary Fields
The ListGrid will automatically
show "view" and "download" icon buttons for binary field types (see ListGridFieldType
). However, you cannot use an upload control
embedded within a ListGrid row to upload files (regardless of whether you use FileItem or
UploadItem). This is because, in the browser's security model, native HTML upload controls
cannot be re-created and populated with a chosen file, and the ListGrid needs to be able to
re-create editors at any time in order to handle loading data on scroll, scrolling editors in
and out of view, adding new rows, changing sort direction, and other use cases.
However you
can create an editor with a FormItem icon
that pops up a
separate Window containing a FileItem in a DynamicForm, so long as the form in the Window saves
the uploaded file immediately rather than trying to have the grid perform the save.
com.smartgwt.client.widgets.form.DynamicForm#getEditorType
,
com.smartgwt.client.widgets.grid.ListGridField#defaultDynamicValue
,
EditorEnterEvent
,
EditorExitEvent
,
com.smartgwt.client.widgets.grid.ListGridField#cellChanged
,
com.smartgwt.client.widgets.grid.ListGridField#formatEditorValue
,
com.smartgwt.client.widgets.grid.ListGridField#parseEditorValue
,
com.smartgwt.client.widgets.grid.ListGridField#change
,
com.smartgwt.client.widgets.grid.ListGridField#changed
,
ListGrid.markRecordRemoved(int)
,
ListGrid.recordMarkedAsRemoved(int)
,
ListGrid.unmarkRecordRemoved(int)
,
ListGrid.markSelectionRemoved()
,
ListGrid.canEditCell(int, int)
,
ListGrid.startEditing()
,
com.smartgwt.client.widgets.grid.ListGrid#getEditorValueMap
,
ListGrid.setEditorValueMap(java.lang.String, java.util.LinkedHashMap)
,
com.smartgwt.client.widgets.grid.ListGrid#getEditorType
,
ListGrid.startEditingNew()
,
ListGrid.getAllEditRows()
,
ListGrid.getEditValues(int)
,
ListGrid.getEditedRecord(int)
,
ListGrid.getEditedCell(int, java.lang.String)
,
ListGrid.setEditValue(int, int, java.lang.Object)
,
ListGrid.getEditValue(int, java.lang.String)
,
ListGrid.clearEditValue(int, java.lang.String)
,
ListGrid.getEditRow()
,
ListGrid.getEditCol()
,
com.smartgwt.client.widgets.grid.ListGrid#getEditField
,
ListGrid.cancelEditing()
,
ListGrid.endEditing()
,
ListGrid.discardAllEdits()
,
ListGrid.discardEdits(int, int)
,
com.smartgwt.client.widgets.grid.ListGrid#saveEdits
,
ListGrid.rowHasChanges(int)
,
ListGrid.hasChanges()
,
ListGrid.cellHasChanges(int, int)
,
ListGrid.saveAllEdits()
,
CellSavedEvent
,
EditCompleteEvent
,
EditFailedEvent
,
EditorEnterEvent
,
RowEditorEnterEvent
,
EditorExitEvent
,
RowEditorExitEvent
,
com.smartgwt.client.widgets.grid.ListGrid#formatEditorValue
,
com.smartgwt.client.widgets.grid.ListGrid#parseEditorValue
,
TreeGrid.startEditingNew()
,
CubeGrid.setEditValue(int, int, java.lang.Object)
,
CubeGrid.getEditValue(int, int)
,
CubeGrid.getEditedRecord(int, int)
,
CubeGrid.getEditedCell(int, int)
,
ListGrid.getEditValues(int)
,
ListGrid.clearEditValue(int, java.lang.String)
,
com.smartgwt.client.widgets.cube.CubeGrid#saveEdits
,
com.smartgwt.client.widgets.cube.CubeGrid#getAllEditCells
,
ListGrid.discardAllEdits()
,
CubeGrid.recordHasChanges(int, int)
,
CubeGrid.hasChanges()
,
ListGrid.saveAllEdits()
,
Calendar.getEventSnapGap()
,
Calendar.getShowQuickEventDialog()
,
com.smartgwt.client.widgets.calendar.Calendar#getEventEditorFields
,
com.smartgwt.client.widgets.calendar.Calendar#getEventDialogFields
,
ListGrid.getRecordCanRemoveProperty()
,
ListGridRecord.get_canRemove()
,
ListGrid.getSaveRequestProperties()
,
ListGridField.getEditorImageURLPrefix()
,
ListGridField.getEditorImageURLSuffix()
,
com.smartgwt.client.widgets.grid.ListGridField#getIcons
,
ListGridField.getEditorIconWidth()
,
ListGridField.getEditorIconHeight()
,
ListGridField.getDefaultIconSrc()
,
ListGridField.getIconVAlign()
,
ListGridField.getCanEdit()
,
com.smartgwt.client.widgets.grid.ListGridField#getDefaultValue
,
ListGridField.getEnterKeyEditAction()
,
ListGridField.getEscapeKeyEditAction()
,
com.smartgwt.client.widgets.grid.ListGridField#getEditorType
,
com.smartgwt.client.widgets.grid.ListGridField#getEditorProperties
,
ListGrid.getModalEditing()
,
ListGridField.getMultiple()
,
com.smartgwt.client.widgets.grid.ListGridField#getEditorValueMap
,
ListGrid.getCanEdit()
,
ListGrid.getRecordEditProperty()
,
ListGridRecord.get_canEdit()
,
ListGrid.getAlwaysShowEditors()
,
ListGrid.getEditByCell()
,
ListGrid.getSaveByCell()
,
ListGrid.getDeferRemoval()
,
ListGrid.getWaitForSave()
,
ListGrid.getStopOnErrors()
,
ListGrid.getAutoSaveEdits()
,
ListGrid.getConfirmCancelEditing()
,
ListGrid.getCancelEditingConfirmationMessage()
,
ListGrid.getConfirmDiscardEdits()
,
ListGrid.getConfirmDiscardEditsMessage()
,
ListGrid.getDiscardEditsSaveButtonTitle()
,
ListGrid.getRowEndEditAction()
,
ListGrid.getListEndEditAction()
,
ListGrid.getEnterKeyEditAction()
,
ListGrid.getEscapeKeyEditAction()
,
ListGrid.getEditEvent()
,
ListGrid.getEditOnFocus()
,
ListGrid.getEditOnF2Keypress()
,
ListGrid.getSelectOnEdit()
,
ListGridField.getCanToggle()
,
ListGrid.getEnumCriteriaAsInitialValues()
,
ListGrid.getLongTextEditorThreshold()
,
ListGrid.getLongTextEditorType()
,
RowEndEditAction
,
EnterKeyEditAction
,
EscapeKeyEditAction
,
EditCompletionEvent
,
ListGridEditEvent