Displays a form that is edited/inserted into the database.
Displays an empty form to the user and inserts a new record in the database.
The NewEdit component presents a number of input fields for inserting, updating or duplicating a record in the database (see "Component mode"). There are different kinds of input fields ("Controls") for different kinds of data, such as text boxes, drop-down lists and so on. For a list of the available controls and their functionality, refer to "Controls" in the Softadmin® documentation. Here we will focus on how the controls can be presented and grouped within a NewEdit menu item.
You can split the input fields in columns. In the above example there are three columns.
If the browser window is too narrow, the input fields will not rearrange. Instead you will get a horizontal scrollbar.
The default buttons are "Save" and "Cancel", but you can change their wording, or specify a completely different set of buttons.
To prevent losing data, the NewEdit component will raise a warning if you try to leave the page without saving changes. It does not appear if you have not made any change to any of the input fields. The warning also appears if you close the browser window.
Every control can display one or more buttons to their right. In this example, the dropdown list with available customers is accompanied by a "New customer" button.
It opens a menu item to create a new customer, displayed in a popup window.
In this example, the user created a new customer named Carl Carlsson. When the new customer is saved, it is automatically added to the customer dropdown in the "Edit car" menu item. Notice that the user did not have to reenter all the other data, like Model, Year model, Price etc, since the New customer menu item took place in a popup window.
These are the controls available in the NewEdit component:
Retrieves metadata for the fields to edit in the form.
Specifies the number of columns to display forthcoming fields and how to allocate those fields to columns.
Possible value | Description |
---|---|
column | The component expects n resultsets to follow and allocates the fields in the same resultset to a separate column. |
row | The component expects one resultset to follow where the n first fields are allocated to row one, the next n fields to row 2, etc... Fields on the same row will be aligned (middle) with each other. |
The alignment of grid columns and InfoSQL values.
Possible value | Description |
---|---|
center | Only applicable to grid columns. |
left | |
right |
Extended description for the field.
Possible value | Description |
---|---|
boolean checkbox | Legacy alias. Use "checkbox" instead. |
boolean dropdown | |
chart | |
checkbox | |
checkbox tree | |
colorpicker | |
date | |
datetime | |
dropdown | |
file | |
file upload area | |
heading | |
heading with checkbox | |
hidden | |
html | Legacy alias. Use "html editor" instead. |
html editor | |
info text | |
listbox | |
multi-autosearch | |
multi-listbox | |
multi-picker | |
multirow | |
password | |
picture | |
radio buttons | |
radio cards | |
signature | |
textarea | |
textbox | |
textbox with autosearch | |
textbox with autosuggest | |
textbox with dropdown | |
textbox with popup | |
time | |
uneditable text |
Possible value | Description |
---|---|
Default | Inherit layout from menu item. |
LabelAbove | Full width, label above. |
LabelLeft | Label to the left. |
NoLabel | Full width, no label. |
Standard | Deprecated. Use LabelLeft instead. |
JavaScript that controls the mandatory status of the field, this overwrites nullchoice if set. This is only available to control types for which the mandatory JavaScript field is visible in the user interface.
Possible value | Description |
---|---|
Hyperlink | |
MailToLink | |
PhoneLink |
Which direction the script is written in. Not to be confused with the CellAlignment property.
Possible value | Description |
---|---|
default | System default. Not useful unless you are trying to override an already explicit text direction on existing field information. |
ltr | Left-to-right (for example English) |
rtl | Right-to-left (for example Arabic) |
The width of the control.
At one point, this was a pixel value. Back when Softadmin used Verdana 10px, and before fields had width-categories. Now, it is just a value that is converted to a width category.
The possible values listed below are just suggestions. For example, both 1 and 30 will be converted to shortest, and both 500 and 9999 to longest.
Possible value | Description |
---|---|
150 | Medium-long |
30 | Shortest |
300 | Long |
500 | Longest |
60 | Short |
90 | Medium short |
Overrides the standard Save and Cancel buttons. The order of the buttons will be the same as the order of the rows.
Example
SELECT
-- Default Save button.
'Save' AS ADMINButtonId,
NULL AS ButtonText,
NULL AS EnforceMandatoryFields,
1 AS IsDefaultButton,
NULL AS IsCancelButton
UNION ALL
SELECT
-- Custom save as draft button.
'SaveDraft' AS ADMINButtonId,
'Save as draft' AS ButtonText,
0 AS EnforceMandatoryFields,
NULL AS IsDefaultButton,
NULL AS IsCancelButton
UNION ALL
SELECT
-- Cancel button.
NULL AS ADMINButtonId,
NULL AS ButtonText,
NULL AS EnforceMandatoryFields,
NULL AS IsDefaultButton,
1 AS IsCancelButton
The specified AdminButtonId is passed to the insert/update procedure in the @AdminButtonId parameter when the button is clicked. Button ID is not used for cancel buttons.
If the ID is NULL, and the button is not a Cancel button, it will be the default save button.
Used to override the default text on the button.
Legacy column. Prefer using IsCancelButton instead.
Using CidStepsBack = 1 is equivalent to using IsCancelButton = 1. Behavior is undefined for non-null values other than 1.
Whether mandatory fields should be forced to contain a value. Used to implement a Save as Draft button, where users are allowed to leave mandatory fields empty in the draft stage but not when submitting the final form.
By default, Save buttons validate mandatory fields. Cancel buttons never do, and is an error to try to make them.
The button acts as a Cancel button, and will not call InsertUpdate when clicked.
This is the default button. Its appearance will be distinct from the other buttons, and the enter and ctrl+s shortcuts will click it. There should be exactly one Default button.
Phrase ID for the text of the button.
If you have fixed lookup tables that fields need for visibility scripts then you can have NewEdit generate JavaScript lookup functions.
For example
SELECT
ComponentId AS ADMINJavaScriptLookup,
HasComponentSql AS componentHasSql,
HasInfoSql AS componentHasInfoSql
FROM dbo.ADMINComponent
will generate JavaScript functions
function componentHasSql(componentId)
function componentHasInfoSql(componentId)
For each column xxx a JavaScript function xxx is generated. The function maps the id values in the ADMINJavaScriptLookup-column to the values in the xxx-column.
If this is a bit column then the SQL value 1 is converted to the JavaScript value true
, and both 0 and NULL are converted to false
.
Allows you to validate the SQL parameters before any other SQL is run in the component. This call is only made if the SQL is a stored procedure and Validate parameters is checked.
Inserts a new record into the database.
NOTE: Fields that both have validation and are hidden (e.g. with Visibility JavaScript) are passed as NULL to the procedure.
May use SoftadminApi.Progress_SetTitle and SoftadminApi.Progress_SetStep.
Displays a user friendly error message to the user. This blocks any forwarding for the user.
Displays a user friendly confirmation message to the user with a delete button as the confirm button. If the user chooses OK the SQL call will be rerun with the parameter @ButtonAction set to 'Delete'.
Displays a user friendly confirmation message to the user with a question style. If the user chooses OK the SQL call will be rerun with the parameter @ButtonAction set to 'Confirm'.
Displays a user friendly confirmation message to the user with a warning style. If the user chooses OK the SQL call will be rerun with the parameter @ButtonAction set to 'Confirm'.
Displays a user friendly info message to the user. When the user clicks OK the user is forwarded.
Displays a user friendly success message to the user. When the user clicks OK the user is forwarded.
The dialog alias of a predefined dialog to show the user. Must be the first column in the result set table. Use multiple result set tables to combine with other forwarding.
Use the menu item "Admin > Dialogs" to register new dialogs or find aliases for existing ones.
Any column without special meaning in the result set with the first column ADMIN_Dialog will be used to make replacements of placeholders in the message and title text.
Additional information to show the developer when using ADMIN_Dialog.
Deprecated. Use ADMIN_CancelMenuItem instead.
Id of the menuitem to execute if the user clicks Cancel in an ADMIN_FORCE dialog (the default being none). This value overrides cancelmenuitemid specified in the query string.
Alias of the menu group to show after execution (instead of former menu item). This value overrides any destination specified by the query string.
Deprecated. Use ADMIN_ForwardMenuGroup instead.
Id of the menu group to show after execution (instead of former menu item). This value overrides any destination specified by the query string.
Deprecated. Use ADMIN_ForwardMenuItem instead.
Id of the menu item to execute after execution (instead of former menu item). This value overrides any destination specified by the query string.
Displays a user friendly error message to the user.
If this column is anything but NULL the popup will be closed and the parent will be reloaded. Only select this column if the menu item is opened in a popup. Avoid using this feature if the opener is a newEdit as that may interrupt the user's ongoing input.
Changes the text of the Cancel button when used with ADMIN_Force, ADMIN_ConfirmWarning, ADMIN_ConfirmQuestion, ADMIN_ConfirmDelete.
Changes the text of the OK button when used with ADMIN_ErrorMessage, ADMIN_ConfirmWarning, ADMIN_ConfirmQuestion, ADMIN_ConfirmDelete, ADMIN_InfoMessage, ADMIN_SuccessMessage, ADMIN_Message, ADMIN_Force, or ADMIN_Forward. ADMIN_Force,
This SQL call may use SoftadminApi.SyncEntity_RaiseChanged.
Use this call to restrict which entries a user is allowed to view and edit, and to log which entries a user views.
Access to a menu item is normally controlled through functions and roles alone but some entities need more fine grained control. For example, a user may have access to the View Member menu item for normal members but not for members with a protected identity.
The menu items a user visits are always logged (in ADMINLogMenuItem) but for sensitive data you may need to log exactly what entries are viewed. Do the logging in this call as the common ways of viewing data (grid and InfoSQL) are not allowed to modify the database.
If you bind a scalar function instead of a stored procedure to this call then its name must end with '_GrantAccess'.
Avoid using nested transactions (since only the outermost matters regarding ROLLBACK or COMMIT). The following code only starts transactions when necessary, ie if one has not already been started. Make sure to look at the @IsUsingLocalTransaction parameter before any COMMITs or ROLLBACKs.
-----------------------
-- Begin transaction --
-----------------------
DECLARE
@IsUsingLocalTransaction bit
IF @@TRANCOUNT = 0
BEGIN
SET XACT_ABORT ON
BEGIN TRANSACTION
SELECT
@IsUsingLocalTransaction = 1
END
--------------------------
-- INSERT/UPDATE/DELETE --
--------------------------
<DML statements>
------------------------
-- Commit transaction --
------------------------
IF @IsUsingLocalTransaction = 1
BEGIN
COMMIT TRANSACTION
END
Example of how dynamic field info can be used to change the properties of fields in a NewEdit.
ALTER PROCEDURE Example.NewEdit_DynamicFieldInfoGetEditFields
AS
BEGIN
-----------------------
-- Fields to NewEdit --
-----------------------
SELECT
-- In this example, this field keeps its original field info
CONVERT(varchar(1000), NULL) AS [ExampleFieldChangedByDynamicFieldInfo1],
-- And these fields will have their field changed by dynamic field info
CONVERT(varchar(1000), NULL) AS [ExampleFieldChangedByDynamicFieldInfo2],
CONVERT(varchar(1000), NULL) AS [ExampleFieldChangedByDynamicFieldInfo3],
CONVERT(varchar(1000), NULL) AS [ExampleFieldChangedByDynamicFieldInfo4]
------------------------
-- Dynamic field info --
------------------------
/*
You don't have to SELECT all dynamic field info in one result set,
the presence of the column [ADMINFieldName] in the result sets tells
Softadmin® that the result set specifies dynamic field info.
The basic structure is to specify the field to change in a column [ADMINFieldName],
the other columns are the properties to be changed. NULL values are
interpreted as keeping the static field info.
*/
SELECT
-- Field to change
'ExampleFieldChangedByDynamicFieldInfo2' AS [ADMINFieldName],
-- Properties to change
'Look how I''ve changed the label but not the description' AS [FieldLabel],
NULL AS [Description] -- NULL value, original description will be used
SELECT
-- Field to change
'ExampleFieldChangedByDynamicFieldInfo3' AS [ADMINFieldName],
-- Properties to change
'Look how I''ve changed the description, width and height' AS [Description],
400 AS [Width],
225 AS [Height]
SELECT
-- Field to change
'ExampleFieldChangedByDynamicFieldInfo4' AS [ADMINFieldName],
-- Properties to change
'Look how I''ve changed the label, type and default value' AS [FieldLabel],
'Uneditable text' AS [FieldType],
'* Try and change me if you can *' AS [DefaultValue]
END
There are many different ways of dividing fields into columns using ADMIN_Columns. The red arrows indicate tab-order.
ALTER PROCEDURE Example.ColumnLayout_GetEditFields
@id int = NULL
AS
BEGIN
/* ONE COLUMN, ONE HEADER */
SELECT
1 AS ADMINColumns;
SELECT
NULL AS HeadingA1,
NULL AS FieldA1,
NULL AS FieldA2,
NULL AS FieldA3,
NULL AS FieldA4
WHERE
1 = 0;
/* TWO INDEPENDENT COLUMNS, ONE HEADER */
SELECT
1 AS ADMINColumns;
SELECT -- The heading must be in its own table to span both columns.
NULL AS HeadingB1
WHERE
1 = 0;
SELECT
2 AS ADMINColumns;
SELECT
NULL AS FieldB1,
NULL AS FieldB2
WHERE
1 = 0;
SELECT
NULL AS FieldB3,
NULL AS FieldB4
WHERE
1 = 0;
/* TWO DEPENDENT COLUMNS, ONE HEADER */
SELECT
1 AS ADMINColumns;
SELECT -- The heading must be in its own table to span both columns.
NULL AS HeadingC1
WHERE
1 = 0;
SELECT
2 AS ADMINColumns,
'ROW' AS ADMINLayout;
SELECT
NULL AS FieldC1,
NULL AS FieldC2,
NULL AS FieldC3,
NULL AS FieldC4
WHERE
1 = 0;
/* TWO COLUMNS, TWO HEADERS */
SELECT
2 AS ADMINColumns;
SELECT
NULL AS HeadingD1,
NULL AS FieldD1,
NULL AS FieldD2
WHERE
1 = 0;
SELECT
NULL AS HeadingD2,
NULL AS FieldD3,
NULL AS FieldD4
WHERE
1 = 0;
/* Dynamic field info */
SELECT
'HeadingA1' AS ADMINFieldName,
'One column, one header' AS FieldLabel,
'Heading' AS FieldType;
SELECT
'HeadingB1' AS ADMINFieldName,
'Two independent columns, one header' AS FieldLabel,
'Heading' AS FieldType;
SELECT
'HeadingC1' AS ADMINFieldName,
'Two dependent columns, one header' AS FieldLabel,
'Heading' AS FieldType;
SELECT
'HeadingD1' AS ADMINFieldName,
'Two columns, left header' AS FieldLabel,
'Heading' AS FieldType;
SELECT
'HeadingD2' AS ADMINFieldName,
'Two columns, right header' AS FieldLabel,
'Heading' AS FieldType;
SELECT
CONCAT('Field', L.Letter, N.Num) AS ADMINFieldName,
CONCAT('Field ', L.Letter, N.Num) AS FieldLabel
FROM (VALUES (1), (2), (3), (4)) AS N(Num)
CROSS JOIN (VALUES ('A'), ('B'), ('C'), ('D')) AS L (Letter);
END;
This code demonstrates how to use the process functions to maintain a progress bar during processing.
CREATE TABLE #ToPostProcess
(
ThingyId int not null
);
/* Choose things to post-process here */
INSERT #ToPostProcess (ThingyId)
SELECT n
FROM SoftadminUtil.Number_Range(1,5);
EXEC SoftadminApi.Progress_SetTitle
@TitleText = 'Post processing thingies';
DECLARE
@CompletedSteps int = 0,
@TotalSteps int = (SELECT COUNT(*) FROM #ToPostProcess);
DECLARE ThingyCursor CURSOR LOCAL FOR
SELECT
ThingyId
FROM
#ToPostProcess;
OPEN ThingyCursor;
WHILE 1=1
BEGIN
EXEC SoftadminApi.Progress_SetStep
@CompletedSteps = @CompletedSteps,
@TotalSteps = @TotalSteps;
DECLARE @ThingyId int;
FETCH ThingyCursor INTO @ThingyId;
IF @@FETCH_STATUS <> 0
BREAK;
/* Post-process Thingy with id @ThingyId here */
-- EXEC Example.Thingy_PostProcess @ThingyId = @ThingyId;
SET @CompletedSteps += 1;
END
CLOSE ThingyCursor;
DEALLOCATE ThingyCursor;
DROP TABLE #ToPostProcess;
The edit fields stored procedure should be named "<Schema>.<Table>_GetEditFields". The insert/update procedureshould be named "<Schema>.<Table>_InsertUpdate" (or just "Insert" or "Update" if the procedure doesn't handle both actions).