If you’ve spent any time on the new Start Tab in Bungee Connect, hopefully you’ve taken the time to explore the Control Examples in that Tab. One of the control examples is for DynamicForm.
The ability to represent different views of the same or related data is a staple of software development. The ability to quickly swap out those views in a way that is natural and fluid for an end user is difficult in traditional web development because of the standard Page Refresh model that permeates the web. We’re going to take a look at how Bungee makes changing out views and dialogs that display data, not only fluid for the end user – but intuitive to implement for the developer.
I want to use this post as a tool to walk you through what’s going on in the simple form swapping example found on the Start Tab. You should import this example from the start page in order to really be able to follow this post. You don’t have to . . . but it will help. Here’s a quick look at where to find that on the start page:
On the Start Tab there are several very interesting and interactive examples of our more popular controls in the Builder. Click on the Experiment with Controls section, then click on DynamicForm. Inside, there are 4 examples of the DynamicForm control. Click on Example 2. On the right side of page you can play with the control by changing the Combobox value and seeing the form beneath it swap out. Notice that there’s no page refresh to show the updated form. It just changes out as you interact with the application. Here’s a screenshot:
Here’s how you can bring your own copy of this example into the builder so that you can follow along:
- On the left menu, click on Example 1 for the DynamicForm.
- On the right side pane, click the 2.Experiment Tab and follow those instructions to copy in your own copy of the example.
Setting Field Types
We’re going to take a look at how Example 2 (Ex2_CurrentObject) works.
In the Control Examples solution you just copied over find the Typelib: DynamicForm project and expand it out. Here’s a screenshot of the class structure for the project:
Although the structure is a bit interrupted because of alphabetization, there are three, what I’ll call, foundation Classes, for this example: Address, Employee and Person. The other classes (the ones that start with Ex) hold the other examples available in this project that we will not be discussing in this post.
Note: Because there are four different examples rolled into one big example project, there’s a lot of inheritance going on between the different example classes. However, for the sake of simplicity and keeping this blog post a bit easier to read, we’re going to focus on Example2 which does not inherit from any other example class.
If you select Ex2_CurrentObject you’ll see the following in the Solution Explorer Detail:
There are three fields: exampleAddress, exampleEmployee and examplePerson which are of type Address, Employee and Person respectively. Let’s look at what that means by looking more closely at the field called examplePerson. Because examplePerson is of type Person it contains all of the fields, forms and function that the Person class contains. Compare the two screenshots below:
The one on the left is the field examplePerson the one on the right is the Person class itself. See how the content of the two objects is the same:
The DynamicForm Control
OK, now that we’re maybe a bit more clear on what happens when you set a Field to be a type of a Class let’s keep going.
Note: See that there are two forms in the Person class. One is called detail and another called readOnlyDetail. If you expand the other foundation classes (Address and Employee) you’ll see that they too have more than one form. Because we have two more fields in our Ex2 class that are of type Address and Employee – they too have those forms. Ex2 uses only the detail form that each contains.
As we continue to explore the Ex2 class you’ll see that there are two more fields and a form. At the top there is a field called currentObject which is of type Object. (In this case that’s useful because when you set a field to type Object it becomes a generic container for any object – which is very useful and the subject of more discussion in a future post.) There’s a string field called objectType which is an enumeration of Null; Address; Person; Employee. You can view that enumeration by selecting the field and looking at the property editor for that field. Find the Enumeration property and there are the values. Finally, at the bottom there’s a form called Ex2_CurrentDetail. Let’s open that form now by double clicking it. I’ll show it below in a screenshot:
There are three controls on this form. At the top left is a label control that is not bound to any object and displays the text “Current Object”. To the right of that is a Combobox control that is bound to the string field objectType so that the Combobox will show the enumeration values of that string. Below that is a DynamicForm control which is bound to object field currentObject. That control is the key to this whole topic. As the name implies, the DynamicForm control will dynamically display your desired form as dictated by the Model code that you write.
There is more than one way to swap out the form that is displayed in a DynamicForm. You can directly change out the form in Bungee Logic using View code (the topic, perhaps, of a subsequent post) – but the way we’re going to swap out the form in this example is by changing the object to which the DyanmicForm is attached. This is more tightly related to the object model architecture intrinsic to the Bungee Connect system; not to mention a great differentiator as well.
Let’s look at how that DynamicForm has been setup. First remember that the control was bound to the object field: currentObject. Remember also that the field currentObject is of type Object – which means that it is a generic container for an Object of any Type. OK, with that understood, select the DynamicForm control and look at the property editor. In the property editor select the Adapter category. We’re interested in two of the properties. Dynamic – which by default is set to DynamicFormAdapter and most of the time will not need to be changed. The other one is the Form property. For this working example that property has already been set to Detail_FA which is the FormAdapter we want the control to use.
OK, here’s where you need to put your thinking cap on and pay attention, cause it’s about to get interesting. Up to this point we’ve only been laying the groundwork for this specific topic. Hopefully you’re clear on what I’ve covered to this point – and I’m just gonna have to assume you are.
Adapters are a very valuable concept in Bungee and there’s a lot of more specific information on the various types of adapters and what each can do in the documentation. I’m just going to talk about the FormAdapter that was setup for this example. In the project we’re working on there’s a FormAdapter named Detail_FA, it looks like this in the tree:
That specific FormAdapter was created explicitly. The DFControl has been set to reference this particular FormAdapter. Let’s look at the detail form found in our examplePerson object. Select the form and look at the Property Editor. If you have selected the correct detail form you’ll see that all of the properties in the Property Editor are disabled. That’s because you’re looking at a form that actually belongs to the Person class. Remember examplePerson is a field of type Person. But you can still see the settings so take a look at the Adapter List property. See that it is a reference to the Detail_FA FormAdapter. Take a look at the detail form for the other exampleAddress and exampleEmployee fields in the Ex2 class. All of the detail forms reference the same FormAdapter. So now we have a common element between the DFControl and all of the detail forms.
Now I need to be careful not to over simplify this. It might appear that all you have to do is tell a DFControl to use a specific FormAdapter and then tell a form to use that same FormAdapter and you’re all set! . . . Nope . . . Remember that the DFControl is actually bound to an Object(Class) that contains the form you want to display and that Object could potentially contain many forms – and in our case it does. So it’s via the FormAdapter that the Object knows which Form to give to the DFControl. The DFControl may display a form but it is bound to an Object! So here’s the correct terminology that will clarify:
- A Control is Bound to an Object
- A Control references a FormAdapter
- A Form references a FormAdapter
- An Object can contain one or many Forms
Here’s a diagram from my whiteboard (Yes, this is just a picture of a whiteboard diagram, but it’s easier than re-drawing the whole thing in some graphics app):
The power lies in the fact that both the binding and the reference can be updated dynamically (during runtime).
So how do we make the form swap out in this case? With the structure mentioned above in place, all we need to do is swap out the Object to which the DFControl is bound. It’s that simple. When the Object changes, the DFControl will re-query for the new Object for any form that references the Detail_FA, and if one is found that new form will be shown.
So let’s look at the code that swaps out the Object to which the DFControl is bound. In the Solution Explorer double click Ex2_CurrentObject class that we’ve been working with. Remember when you used this example, that the form swapped out when you changed the selection in the Combobox. Remember also that the Combobox is tied to the string field objectType which is simply an enumeration.
In the code:
- Select the line of code that says: Public stringobjectType = ‘Address’;
This is the string Field objectType in our class and note in the Property Explorer that its default value is Address. That way the form initializes to use that specific form because of the code that follows.
- Click the + symbol to expand the string field objectType
- expand the onChange code statement
- expand the condition (which is actually a Case statement) and we can see in there all the possible conditions that he objectType field can be (Null, Address, Person, Employee). In each Case statement there’s an Assignment statement that sets the object field currentObject to be the field that matches the selection.
- Expand the case(objectType == “Address”) line and you’ll see that specific case’s Assignment statement: currentObject = exampleAddress
So, if you’re using the form and you select Address from the Combobox then the currentObject is set to exampleAddress. Here’s a screenshot to help follow the logic:
Note: in this screenshot I’ve added comments to help follow the path. In the actual example, the comment lines will not be there
As we said at the beginning of this section, each time that object gets swapped out by this code the DFControl asks the new object for any form that references the Detail_FA FormAdapter.
OK, so at the beginning I said this was gonna be simple. Really, it actually was. At least the example was simple. But implementing this sort of interaction requires some foundational knowledge around using Bungee and a basic understanding of Object based development that I had to cover in this post so that it could be consumed by a broad audience. What it comes down to is this: the DynamicForm control is a powerful control and in this case: power = indredible value for your end users. But also in this case, that same power comes with a certain level of implementation detail and execution complexity. Once you get your head around what I covered in this post, you’ll be able to explore some really interesting things in Bungee with your own applications – go off the beaten path, so to say.
Good luck with that, I hope this was worth the read.