Shuttle Values to and from a Popup Data Form
Overview
As the amount of data on your data forms grows, it becomes harder and harder to collect all the data on a single data form. Think solicitors, recognition, campaigns, benefits, etc. on the payment add form. We can use helper "popup" data forms to collect additional data for the solicitors, recognition, etc. The overall idea is to have a parent data form that calls upon a popup data form to collect the additional child data. The popup data form is created with a special spec type called a "Custom UI Model Meta Data" spec. When the popup data form closes, you can programmatically collect the data from the popup data form and place that data onto the parent data form using hidden form fields. After the data is on the parent data form, you can save the parent data form and have the save implementation place the data in the database, as you normally would.
Use a "Custom UI Model Meta Data" Spec to Create a Popup Data Form
So, to collect the additional data, you need a user interface data entry screen. This involves using a separate "popup" data form to collect the extra data, like solicitors for a payment. These popup forms are created using "Custom UI Model Meta Data" catalog item template within Visual Studio. It is like a Data Form Spec but without the save implementation. The CustomUIModelMetadata element describes the form metadata used to generate a UI model and HTML. Unlike traditional specs, this XML document is never loaded into the database and simply servers as a common means to define form metadata. In other words, it is used to provide a UI data entry screen to collect the data from the user without actually saving the data to the database. Below is an example:
<CustomUIModelMetadata
xmlns="bb_appfx_customuimodelmetadata"
xmlns:common="bb_appfx_commontypes"
ID="d4a89903-0baa-470e-afa6-96f7a9f0865e"
Name="Child Popup Data Form"
Description="REPLACE_WITH_DESCRIPTION"
Author="$author$"
FormHeader="REPLACE_WITH_HEADER">
<FormMetaDataxmlns="bb_appfx_commontypes">
<FormFields>
<FormFieldFieldID="FIELD1" Caption="Field 1" DataType="String" MaxLength="10" />
<FormFieldFieldID="FIELD2" Caption="Field 2" DataType="String" MaxLength="20" />
<FormFieldFieldID="FIELD3" Caption="Field 3" DataType="String" />
</FormFields>
</FormMetaData>
</CustomUIModelMetadata>
This CustomUIModelMetadata spec represents the popup data form to collect the child data. The CustomUIModelMetadata spec does not include save or load implementations. You can put UIActions on this spec, and you can have UI fields, tabs, form fields, and custom HTML layout. You can even create a UIModel from this spec…
Create a UIModel for Popup Data Form
You should create a UI Model from the CustomUIModelMetadata spec. You can use the UI Model wizard to generate a UIModel. It is the UIModel which represents the data and UI events for the popup data form.
Within the parent data form, you can open the popup data from by using a UIAction:
<UIAction ActionID="COLLECTCHILDDATAPOPUPACTION" Description="Open child data using popup form
defined by a UIModel generated from a CustomUIModelMetadata spec.">
<ShowCustomForm>
<ModelComponent AssemblyName="Blackbaud.CustomFx.Fundraising.UIModel.dll"
ClassName="Blackbaud.CustomFx.Fundraising.UIModel.Child Popup Data Form" />
</ShowCustomForm>
</UIAction>
Shuttle the Data to and from the Popup Data Form
You can interact with the popup data form's UI Model using the parent data form's UI Model. It is the responsibility of the PARENT data form UI model code to shuttle form values back and forth to the popup data form UI Model. The parent data form's UI Model code handles the InvokeAction and CustomFormConfirmed events emitted by the popup form. You can use these events to shuttle the popup form values back and forth to the parent data form. When the popup data form is opened from the parent, the InvokeAction event is fired and can be handled by the UI Model code within the payment add form. When the InvokeAction event is handled, we move data into the popup data form from the payment add form/parent form. Here's a sample of populating the popup form by handling the popup form's InvokeAction event. This code shuttles the solicitor data from the parent payment add form to the solicitors popup form.
Private Sub EditSolicitorsActionHandler(ByVal sender As Object, ByVal e As UIModeling.Core.ShowCustomFormEventArgs)
Handles _donationsolicitorsaction.InvokeAction
'copy the Donation/Other Solicitors to the custom “popup” form model from the parent data form
Dim model = TryCast(e.Model, SolicitorsFormUIModel)
If model Is Nothing Then Exit Sub
model.GIFTAMOUNT.Value = AppliedAmount()
If _baseCurrencyID IsNot Nothing Then
model.BASECURRENCYID.Value = _baseCurrencyID.Value
model.SOLICITORS.DefaultItem.BASECURRENCYID.Value = _baseCurrencyID.Value
End If
Dim solicitorsCollection As GenericCollectionField = Nothing
If sender Is _donationsolicitorsaction Then
solicitorsCollection = _donationsolicitors
model.OPPORTUNITYID.Value = _donationopportunityid.Value
ElseIf sender Is _othersolicitorsaction Then
solicitorsCollection = _othersolicitors
ElseIf sender Is _umgsolicitorsaction Then
solicitorsCollection = _umgsolicitors
End If
For Each item In solicitorsCollection.Value
Dim row = model.SOLICITORS.Value.AddNew()
row.ID.Value = DirectCast(item.Fields("ID").ValueObject, Guid)
row.CONSTITUENTID.SearchDisplayText = DirectCast(item.Fields("CONSTITUENTID"),
SearchListField(Of Guid)).SearchDisplayText
row.CONSTITUENTID.Value = DirectCast(item.Fields("CONSTITUENTID").ValueObject, Guid)
row.AMOUNT.Value = DirectCast(item.Fields("AMOUNT").ValueObject, Decimal)
row.SEQUENCE.Value = DirectCast(item.Fields("SEQUENCE").ValueObject, Integer)
Next
End Sub
When users save the popup data form, the CustomFormConfirmed event is fired and handled by the UIModel code within the payment add form, as well. We move data from the popup data form to a collection of form fields on the parent form. After the data is on the parent form, it can be saved to the database. The solicitor data is stored within the payment add form (Parent form) using collection form fields. When the save occurs on the payment add form, the data is passed from parent data form's form fields to the save implementation for the data form.
Private Sub SolicitorsFormConfirmedHandler(ByVal sender As Object, ByVal e As Modeling.Core.CustomFormConfirmedEventArgs)
Handles _donationsolicitorsaction.CustomFormConfirmed
'copy from the custom “popup ”form model to the parent data form
Dim model = TryCast(e.Model, SolicitorsFormUIModel)
If model Is Nothing Then Exit Sub
Dim solicitorsCollection As GenericCollectionField = Nothing
If sender Is _donationsolicitorsaction Then
solicitorsCollection = _donationsolicitors
ElseIf sender Is _othersolicitorsaction Then
solicitorsCollection = _othersolicitors
ElseIf sender Is _umgsolicitorsaction Then
solicitorsCollection = _umgsolicitors
End If
solicitorsCollection.Clear()
For Each row In model.SOLICITORS.Value
Dim item = solicitorsCollection.NewItem()
item.Fields("ID").ValueObject = row.ID.Value
DirectCast(item.Fields("CONSTITUENTID"), SearchListField(Of Guid)).SearchDisplayText = row.CONSTITUENTID.SearchDisplayText
item.Fields("CONSTITUENTID").ValueObject = row.CONSTITUENTID.Value
item.Fields("AMOUNT").ValueObject = row.AMOUNT.Value
item.Fields("SEQUENCE").ValueObject = row.SEQUENCE.Value
solicitorsCollection.Insert(item)
Next
End Sub
Real World Example
As for a real world example, let's take the Payment add form. The payment add form utilizes the PaymentAddFormUIModel for UI event handlers. The PaymentAddFormUIModel class abstracts common payment UI event duties to the PaymentHelper.vb class. PaymentHelper.vb class uses the PaymentApplicationHelper.vb helper class which includes UI code just payment applications, such as solicitors. So at this point with the Payment Add Form UI running at run time, all the code within PaymentAddFormUIModel, PaymentHelper, and PaymentApplicationHelper is ready on tap to respond to UI events.
The payment add form relies on a popup form to collect the solicitors, which is represented in the SolicitorsFormUIModel. On the Payment Add Form, a collection of form fields named DONATIONSOLICITORS holds the solicitor data managed by SolicitorsFormUIModel which is called upon when the DONATIONSOLICITORSACTION UIAction button. The SolicitorsFormUIModel represents the UI events for the custom popup data form that users see when they click the DONATIONSOLICITORSACTION UIAction button.
When users click the DONATIONSOLICITORSACTION UIAction button, the InvokeAction event is fired. The InvokeAction event is handled by the EditSolicitorsActionHandler within the PaymentApplicationHelper class. The EditSolicitorsActionHandlersub populates the forms fields on the popup form represented in memory by the SolicitorsFormUIModel with the DONATIONSOLICITORS form values from the Payment Add Form.
When users save (confirm) the SolicitorsFormUIModel popup form, the CustomFormConfirmed event is fired and handled by the SolicitorsFormConfirmedHandler within the PaymentApplicationHelper class. SolicitorsFormConfirmedHandler takes the values from the form fields within the popup form (SolicitorsFormUIModel) and saves them to form fields on the DONATIONSOLICITORS form values from the Payment Add Form.