In Part 2 of this series, I showed you how to convert your XMod GridView to a grid in XMod Pro. In Part 3, I'll add the ability to add, edit, and delete records.
Before beginning, make sure that you've created the form and template as outlined in Parts 1 and 2 of this series. Then, add an XMod Pro module to your page and configure it to use the form and template.
Before diving into the code, let's look once again at our nearly complete template:
<xmodt:Template>
<ListDataSource CommandText="SELECT LaptopModel, ServiceTag, SerialNumber, LaptopName, Owner, Location FROM LaptopInventory ORDER BY LaptopModel, LaptopName" />
<HeaderTemplate>
<table>
<tbody>
<tr>
<th>Laptop Model</th>
<th>Service Tag</th>
<th>Serial Number</th>
<th>Laptop Name</th>
<th>Owner</th>
<th>Location</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>[[LaptopModel]]</td>
<td>[[ServiceTag]]</td>
<td>[[SerialNumber]]</td>
<td>[[LaptopName]]</td>
<td>[[Owner]]</td>
<td>[[Location]]</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</table>
</FooterTemplate>
</xmod:Template>
Creating An Add New Record Link
Since we need to add some records before we can display, edit, or delete them, we'll begin by adding an add button to the template. This can be a button, clickable image, or hyperlink. We'll display it as a hyperlink.
All we need to do is add an <xmod:AddLink>
tag to our template. We could put the tag in the <HeaderTemplate>
or the <FooterTemplate>
. However, neither of these will show up if no records are being displayed. This would make it impossible to add records because the link to do so would never appear.
So, what we'll do is add the tag outside the <xmod:Template>
tag. This is a great new feature in XMod Pro – it allows you to put multiple <xmod:Template>
tags in a single module instance. Even though we're only using one template tag, we can take advantage of this feature. It means we can add certain XMod Pro tags as well as our own HTML outside the template tag to aid in layout. So, here's the relevant portion of our template:
. . .
<FooterTemplate>
</tbody>
</table>
</FooterTemplate>
</xmod:Template>
<xmod:AddLink Text="Add New Laptop" />
If you save your changes, the module will look similar to this:
If you click the link, you'll see the AddForm:
Go ahead and fill out the form:
And click the "Add to Inventory" button. You should see results similar to this:
We can always make it look pretty by adding CSS classes and/or tweaking the HTML. Our purpose in this tutorial, though, is to work through the conversion process between XMod and XMod Pro, so I'll leave the "prettifying" as an exercise to you.
Adding A Command Column
Now that we've added a record, how can we edit it? Well, we're going to need an Edit button to initiate the process. So, let's make room for that now. All we need to do is add another column to our table. That involves adding another table header (<th> </th>) to the <HeaderTemplate>
and another table cell (<td> </td>) to the <ItemTemplate>
. If we were using an <AlternatingItemTemplate>
, we would also add a table cell to that. Changes are highlighted in red below.
<xmod:Template>
<ListDataSource CommandText="SELECT InventoryId, LaptopModel, ServiceTag, SerialNumber, LaptopName, Owner, Location FROM LaptopInventory ORDER BY LaptopModel, LaptopName" />
<HeaderTemplate>
<table>
<tbody>
<tr>
<th> </th>
<th>Laptop Model</th>
<th>Service Tag</th>
<th>Serial Number</th>
<th>Laptop Name</th>
<th>Owner</th>
<th>Location</th>
</tr>
</HeaderTemplate>
<ItemTemplate>
<tr>
<td>
<xmod:EditLink Text="Edit">
<parameter name="InventoryId" value='[[InventoryId]]' />
</xmod:EditLink>
</td>
<td>[[LaptopModel]]</td>
<td>[[ServiceTag]]</td>
<td>[[SerialNumber]]</td>
<td>[[LaptopName]]</td>
<td>[[Owner]]</td>
<td>[[Location]]</td>
</tr>
</ItemTemplate>
<FooterTemplate>
</tbody>
</table>
</FooterTemplate>
</xmod:Template>
We've actually made three changes to the template. In <HeaderTemplate> we've added a blank header cell (<th>
& </th>
) for our command button column. Second, in <ItemTemplate>
, we've added another table cell that contains our Edit link button. Let's take a look at that tag in more detail:
<xmod:EditLink Text="Edit">
<parameter name="InventoryId" value='[[InventoryId]]' />
</xmod:EditLink>
The <xmod:EditLink>
tag has its Text set to "Edit". This will be the caption for the link at run-time. The tag also has a child tag: <parameter>
. This is something new to XMod users. The <parameter>
tag allows us to pass information to the form when we're editing the record. The form can then use that information to grab the record that needs to be edited.
We've given the <parameter>
a name of "InventoryId". Remember this, because we'll need to use it in our form (more on that later). We've also assigned a value to the <parameter>
, using a field token. At run-time, this value will be replaced by the record's InventoryId. Notice also that the attribute is delimited with single quotes (') rather than the standard double-quotes ("). This is required whenever we use field tokens as an attribute value.
The third change we made was to the <ListDataSource>
. Since we now need to use the value of the InventoryId field, we'll need to ensure we've retrieved it from the database. So, I've added InventoryId to the list of fields that are SELECT'ed.
After saving the template, it should look like this (the Edit link has been circled):
If you click the Edit link now, you'll get a No Record Found message. That's because we need to setup our form to edit the record.
Editing Records – Creating the Edit Form
We've already created a form to add records, called the <AddForm>
. Now we need to add an <EditForm>
tag to our form definition. This will be used when adding records. So, let's edit our original form. We'll start out by copying and pasting our <AddForm>
tag and its contents. This will create a duplicate of the <AddForm>
in our form definition. Next, change the second <AddForm>
and </AddForm>
tags to <EditForm>
and </EditForm>
, respectively:
<AddForm>
<SubmitCommand CommandText="INSERT INTO LaptopInventory(LaptopModel, ServiceTag, SerialNumber, LaptopName, Owner, Location) VALUES(@LaptopModel, @ServiceTag, @SerialNumber, @LaptopName, @Owner, @Location)" />
<table>
<tr>
<td><label for="LaptopModel">Laptop Model:</label></td>
<td><TextBox id="LaptopModel" datafield="LaptopModel" /></td>
</tr>
<tr>
<td><label for="ServiceTag">Service Tag:</label></td>
<td><TextBox id="ServiceTag" datafield="ServiceTag" /></td>
</tr>
<tr>
<td><label for="SerialNumber">Serial Number:</label></td>
<td><TextBox id="SerialNumber" datafield="SerialNumber" /></td>
</tr>
<tr>
<td><label for="LaptopName">Laptop Name:</label></td>
<td><TextBox id="LaptopName" datafield="LaptopName" /></td>
</tr>
<tr>
<td><label for="Owner">Owner:</label></td>
<td><TextBox id="Owner" datafield="Owner" /></td>
</tr>
<tr>
<td><label for="Location">Location:</label></td>
<td><TextBox id="Location" datafield="Location" /></td>
</tr>
<tr>
<td colspan="2"><AddButton text="Add to Inventory" /></td>
</tr>
</table>
</AddForm>
<EditForm>
<SubmitCommand CommandText="INSERT INTO LaptopInventory(LaptopModel, ServiceTag, SerialNumber, LaptopName, Owner, Location) VALUES(@LaptopModel, @ServiceTag, @SerialNumber, @LaptopName, @Owner, @Location)" />
<table>
<tr>
<td><label for="LaptopModel">Laptop Model:</label></td>
<td><TextBox id="LaptopModel" datafield="LaptopModel" /></td>
</tr>
<tr>
<td><label for="ServiceTag">Service Tag:</label></td>
<td><TextBox id="ServiceTag" datafield="ServiceTag" /></td>
</tr>
<tr>
<td><label for="SerialNumber">Serial Number:</label></td>
<td><TextBox id="SerialNumber" datafield="SerialNumber" /></td>
</tr>
<tr>
<td><label for="LaptopName">Laptop Name:</label></td>
<td><TextBox id="LaptopName" datafield="LaptopName" /></td>
</tr>
<tr>
<td><label for="Owner">Owner:</label></td>
<td><TextBox id="Owner" datafield="Owner" /></td>
</tr>
<tr>
<td><label for="Location">Location:</label></td>
<td><TextBox id="Location" datafield="Location" /></td>
</tr>
<tr>
<td colspan="2"><AddButton text="Add to Inventory" /></td>
</tr>
</table>
</EditForm>
Now we're going to focus on our newly created <EditForm>
. The first change we need to make is to add a <SelectCommand>
tag. This is similar to the <SubmitCommand>
tag we saw in the <AddForm>
and which we'll use again in the <EditForm>
. The <SelectCommand>
gets executed when the form is loaded. So, we're going to take the parameter passed by the <xmod:EditLink>
in the template and use it to grab the record:
<SelectCommand CommandText="SELECT InventoryId, LaptopModel, ServiceTag, SerialNumber, LaptopName, Owner, Location FROM LaptopInventory WHERE InventoryId = @InventoryId" />
In the command we're selecting all the fields in the LaptopInventory table for the record with an InventoryId of @InventoryId. @InventoryId is the placeholder for the value that was passed-in by our <xmod:EditLink>
tag. An important point to remember here is that the field names in the SELECT command must match the DataField attributes in our controls in order for them to be bound correctly.
Next, we need to modify the <SubmitCommand>
. In the <EditForm>
, when the user submits the form, we want to update the record we're editing rather than create a new one.
<SubmitCommand CommandText="UPDATE LaptopInventory SET LaptopModel = @LaptopModel, ServiceTag = @ServiceTag, SerialNumber = @SerialNumber, LaptopName = @LaptopName, Owner = @Owner, Location = @Location WHERE InventoryId = @InventoryId" />
This is a standard UPDATE SQL command. The important bits to remember here are that the @Parameter parameters should link up with the DataField attributes in your controls. Since control tags only have one DataField attribute, practically this means that the field names you use in your <SelectCommand>
must be the same as the @ parameter names in your <SubmitCommand>
.
Let's see what our <EditForm>
looks like now:
<EditForm>
<SelectCommand CommandText="SELECT InventoryId, LaptopModel, ServiceTag, SerialNumber, LaptopName, Owner, Location FROM LaptopInventory WHERE InventoryId = @InventoryId" />
<SubmitCommand CommandText="UPDATE LaptopInventory SET LaptopModel = @LaptopModel, ServiceTag = @ServiceTag, SerialNumber = @SerialNumber, LaptopName = @LaptopName, Owner = @Owner, Location = @Location WHERE InventoryId = @InventoryId" />
<table>
<tr>
<td><label for="LaptopModel">Laptop Model:</label></td>
<td><TextBox id="LaptopModel" datafield="LaptopModel" /></td>
</tr>
<tr>
<td><label for="ServiceTag">Service Tag:</label></td>
<td><TextBox id="ServiceTag" datafield="ServiceTag" /></td>
</tr>
<tr>
<td><label for="SerialNumber">Serial Number:</label></td>
<td><TextBox id="SerialNumber" datafield="SerialNumber" /></td>
</tr>
<tr>
<td><label for="LaptopName">Laptop Name:</label></td>
<td><TextBox id="LaptopName" datafield="LaptopName" /></td>
</tr>
<tr>
<td><label for="Owner">Owner:</label></td>
<td><TextBox id="Owner" datafield="Owner" /></td>
</tr>
<tr>
<td><label for="Location">Location:</label></td>
<td><TextBox id="Location" datafield="Location" /></td>
</tr>
<tr>
<td colspan="2"><AddButton text="Add to Inventory" /></td>
</tr>
</table>
</EditForm>
Now, the InventoryId of the chosen record has been passed-in to the <EditForm>
and has been used to retrieve the record. However, when we submit the form, that information will be lost unless we store it somewhere. So, we'll add another <TextBox>
to our form, bind it to the InventoryId field, and hide it from view. That way the InventoryId will be available (and unmodifiable by the user) to the <SubmitCommand>
. Since the text box will be hidden, we can place it anywhere in our form. Let's add it before the closing </EditForm>
tag:
<EditForm>
<SelectCommand CommandText="SELECT InventoryId, LaptopModel, ServiceTag, SerialNumber, LaptopName, Owner, Location FROM LaptopInventory WHERE InventoryId = @InventoryId" />
<SubmitCommand CommandText="UPDATE LaptopInventory SET LaptopModel = @LaptopModel, ServiceTag = @ServiceTag, SerialNumber = @SerialNumber, LaptopName = @LaptopName, Owner = @Owner, Location = @Location WHERE InventoryId = @InventoryId" />
<table>
<tr>
<td><label for="LaptopModel">Laptop Model:</label></td>
<td><TextBox id="LaptopModel" datafield="LaptopModel" /></td>
</tr>
<tr>
<td><label for="ServiceTag">Service Tag:</label></td>
<td><TextBox id="ServiceTag" datafield="ServiceTag" /></td>
</tr>
<tr>
<td><label for="SerialNumber">Serial Number:</label></td>
<td><TextBox id="SerialNumber" datafield="SerialNumber" /></td>
</tr>
<tr>
<td><label for="LaptopName">Laptop Name:</label></td>
<td><TextBox id="LaptopName" datafield="LaptopName" /></td>
</tr>
<tr>
<td><label for="Owner">Owner:</label></td>
<td><TextBox id="Owner" datafield="Owner" /></td>
</tr>
<tr>
<td><label for="Location">Location:</label></td>
<td><TextBox id="Location" datafield="Location" /></td>
</tr>
<tr>
<td colspan="2"><AddButton text="Add to Inventory" /></td>
</tr>
</table>
<TextBox id="InventoryId" DataField="InventoryId" DataType="Int32" visible="False" />
</EditForm>
Notice that we've set the DataField
to InventoryId (our key field) and have also added the DataType
attribute. With previous controls, we didn't have to use this attribute because "String" (i.e. text) is the default data type for <TextBox>
controls and the columns in our table all take string values. By specifying "Int32" we are telling XMod Pro the value coming from the Text Box should be treated as a 32 bit integer, which matches the "int" datatype of the InventoryId column in the table. Other datatype values are possible and are listed in the XMod Pro help file.
By setting the Visible
attribute to False, we ensure the value will not be displayed in the page. Additionally, the control will not be visible when viewing the HTML source of the page – an added security measure.
Finishing Up
Finally, we need to change our <AddButton>
to an <UpdateButton>
and we'll also add a way to cancel the change with a <CancelButton>:
<EditForm>
<SelectCommand CommandText="SELECT InventoryId, LaptopModel, ServiceTag, SerialNumber, LaptopName, Owner, Location FROM LaptopInventory WHERE InventoryId = @InventoryId" />
<SubmitCommand CommandText="UPDATE LaptopInventory SET LaptopModel = @LaptopModel, ServiceTag = @ServiceTag, SerialNumber = @SerialNumber, LaptopName = @LaptopName, Owner = @Owner, Location = @Location WHERE InventoryId = @InventoryId" />
<table>
<tr>
<td><label for="LaptopModel">Laptop Model:</label></td>
<td><TextBox id="LaptopModel" datafield="LaptopModel" /></td>
</tr>
<tr>
<td><label for="ServiceTag">Service Tag:</label></td>
<td><TextBox id="ServiceTag" datafield="ServiceTag" /></td>
</tr>
<tr>
<td><label for="SerialNumber">Serial Number:</label></td>
<td><TextBox id="SerialNumber" datafield="SerialNumber" /></td>
</tr>
<tr>
<td><label for="LaptopName">Laptop Name:</label></td>
<td><TextBox id="LaptopName" datafield="LaptopName" /></td>
</tr>
<tr>
<td><label for="Owner">Owner:</label></td>
<td><TextBox id="Owner" datafield="Owner" /></td>
</tr>
<tr>
<td><label for="Location">Location:</label></td>
<td><TextBox id="Location" datafield="Location" /></td>
</tr>
<tr>
<td colspan="2"><UpdateButton Text="Save Changes" /> <CancelButton Text="Cancel" /></td>
</tr>
</table>
<TextBox id="InventoryId" DataField="InventoryId" DataType="Int32" Visible="False" />
</EditForm>
Save your form and try out your application. I have clicked the Edit link in the grid view and edited the Laptop Model to read "Sony Vaio 3200":
When I click "Save Changes", I can see the updated record in my grid:
In the next installment, we'll start deleting records…