Field editing in the Structural Editing developer sample form
Field editing in a Microsoft Office InfoPath 2003 form occurs when data is entered directly into a form field (usually a text box control) as a user fills out a form. The data that is entered is stored as a value of the element or attribute of the XML field (element or attribute) in the underlying XML document that the control is bound to. For example, in the Structural Editing developer sample form, text boxes are used for editing the data contained in the Part Number, Description, Quantity, and Unit Price fields.
Field editing usually occurs when a user enters data within a control on a form; the data that the user enters is stored in the form's underlying XML document. However, you can also use scripting code to manipulate the data contained in the form's underlying XML document by modifying the XML document itself. If the form includes a control such as a text box that is bound to the modified data, the data displayed in the form will be updated automatically.
Using controls for field editing
When working with a form in design mode, you can drag controls from the Controls task pane onto the form that will allow users to enter data. These controls are bound to the form's XML data source. Some controls are used for field editing, such as text boxes, expression boxes, rich text boxes, and list boxes, while others are used for structural editing, such as optional sections, repeating sections, repeating tables, and lists.
After you have placed a control on a form, you can use the Properties dialog box for the control, available by right-clicking the control while in design mode, to set various properties of the control, including its default value, data validation, conditional formatting, placeholder text, and other data and display options.
When you drag a field editing control onto a form and then bind that control to a field, InfoPath will usually create an entry in the form definition (.xsf) file that specifies the editing component, the XML fields that the editing component is bound to, and other properties of the control such as spelling checker and auto-complete.
Editing components are the InfoPath implementation of some of the controls that are used in a form, and they are set in the component attribute of the editWith element in the .xsf file. The editing components used by InfoPath are xField, xTextList, xCollection, xOptional, xReplace, and xImage.
In the following example from the the Structural Editing developer sample form, the editing element of the .xsf file contains information about the Unit Price field. The Unit Price field is implemented as a text box that, in the .xsf file, corresponds to an editing component called xField; the xField editing component is listed in the component attribute of the editWith element. The field that the editing component is bound to is specified in the item attribute of the xmlToEdit element.
<xsf:editing>
...
<xsf:xmlToEdit
name="14"
item="/invoice/list/item/unitPrice">
<xsf:editWith
component="xField"
proofing="no"
autoComplete="no">
</xsf:editWith>
</xsf:xmlToEdit>
...
</xsf:editing>
Using script for field editing
Script editing in an InfoPath form occurs when a user is filling out a form, and the types of editing actions that the user can perform are determined by custom scripting code written by form developers using Microsoft Script Editor (MSE). For example, if a row in the Structural Editing developer sample form Parts table is selected, and an item from the Apply Discount menu on the Part Toolbar custom toolbar is clicked, the Discount and Total fields for the row in the Parts table are updated.
Note InfoPath supports writing script in Microsoft VBScript and Microsoft JScript. However, you cannot mix the scripting languages used within a single form.
When a user selects a discount to apply to a row in the Parts table, the OnClick event for the selected discount button is called, which in turn calls the ApplyDiscount custom function. The ApplyDiscount function uses the GetSelectedNodes method of the View object, accessed through the XDocument object, to return a collection of XML nodes that correspond to the fields, sections, or rows that are currently selected in the form. If rows in the Parts table are selected, the function uses a for loop to iterate through the collection, calling the ApplyDiscountToItem custom function to update the Discount field in each row.
Note InfoPath does not support the creation of button OnClick events for custom buttons in design mode. To create the event handlers for custom buttons, you must manually type the OnClick event handler into your form's script file.
If no rows are selected, the ApplyDiscount custom function uses the GetContextNodes method of the View object to return a collection of XML nodes that are based on the user's current context (selection or insertion point). If the current selection is within one of the rows, the ApplyDiscountToItem custom function is used to update the Discount field in that row. If the current selection is not within one of the rows, the ApplyDiscount custom function calls the Prompt custom function to ask the user if he or she wants to apply the discount to all of the rows in the Parts table. The following is the code used for the ApplyDiscount custom function in the Structural Editing developer sample form's logic.js script file:
function ApplyDiscount(intPercentage)
{
var objSelectedItems = null;
var objContextNodes = null;
var blnAppliedDiscount = false;
// Get the XML node selection corresponding to the current HTML selection.
objSelectedItems = XDocument.View.GetSelectedNodes();
// Apply the discount to the selected items.
if (objSelectedItems.Count > 0)
{
// Apply discount to each of the selected items.
for (var i = 0; i < objSelectedItems.Count; i++)
{
if (objSelectedItems.Item(i).nodeName == "item")
{
ApplyDiscountToItem(objSelectedItems.Item(i), intPercentage);
blnAppliedDiscount = true;
}
}
}
// If there is no selection or the selection was not on an item node,
// keep looking for something to do.
if (!blnAppliedDiscount)
{
// Get a collection of all of the XML nodes that are bound to a control
// on the view, starting at the node which currently has focus.
objContextNodes = XDocument.View.GetContextNodes();
// Scan the list of context nodes for an item node and if one is found
// apply the discount to it.
for (var i = 0; i < objContextNodes.Count; i++)
{
if (objContextNodes.item(i).nodeName == "item")
{
ApplyDiscountToItem(objContextNodes.item(i), intPercentage);
blnAppliedDiscount = true;
break;
}
}
// If there weren't any context nodes found (i.e. nothing is selected)
// or there were no item nodes (i.e. focus is not within the part list)
// give the user the option of applying the discount to every item.
if (objContextNodes.Count == 0 || blnAppliedDiscount==false)
{
if (Prompt("There are no items selected. Do you want to apply the
discount to each item?", "Structural Editing Developer Sample Form", "YN"))
{
var objItemNodes = XDocument.DOM.selectNodes("//item");
// Apply discount to each of the items.
for (var i = 0; i < objItemNodes.length; i++)
{
ApplyDiscountToItem(objItemNodes.item(i), intPercentage);
}
}
}
}
}
The ApplyDiscountToItem custom function uses the standard selectSingleNode method of the XML Document Object Model (DOM) to set the text property of the specified XML node argument, and it sets the discountApplied attribute of the node to True.
function ApplyDiscountToItem(objItemNode, intPercentage)
{
var objDiscountNode = null;
// Set discount value to specified percentage.
objDiscountNode = objItemNode.selectSingleNode("discount");
objDiscountNode.text = intPercentage;
// Mark the node as having the discount applied to it or not.
objItemNode.setAttribute("discountApplied",
intPercentage>0 ? "true" : "false");
}
When the Discount field has been updated, its OnAfterChange event occurs and the totals for the Parts table are calculated by the Calculate custom function. To see the code for the Calculate custom function, open the Structural Editing developer sample form in design mode, and then open Microsoft Script Editor.