This documentation supports the 19.05 version of BMC Helix Platform. 
To view an earlier version, select 19.02 from the Product version menu.

Creating a view to order from a dish

We now have a fairly complete application: we can manage the menu (restaurants and dishes), order a new dish, and track it through its lifecycle. If you are eager to get started with the application's order process, you could skip this section, since it is not really adding any back-end functionality. However, from a learning perspective, going through the following exercise will help you learn about some powerful techniques, including displaying pictures in a view, and calling a process directly from a view to help control your logic. 

Let's consider the current state of the Lunch Tutorial application. You might notice that the user experience of using the New Order view we created earlier is not ideal. For example, users have to pick a restaurant, then pick the dish from the drop-down. A better experience, and one more natural for users, would be to browse through the available dishes, and simply order one, as one would from any e-commerce site.  Also, recall that we have defined restaurants and dishes to have photos and long descriptions; but these aren't much use to the user unless they can look at them before choosing to order.

We can solve this by creating a pair of new views: a Dishes view (independent of restaurant choice), and a Dish view to show all the details of a dish and allow quick ordering of it. This will require some view-building techniques that are a bit more advanced that what we have seen with previous views, with even more nesting of containers and use of advanced button actions.

Note: if you have not yet installed the util-lib package that was described at the beginning of this module of the tutorial, you will need it now in order to show pictures in your views.  If you don't have it, you can download com.example.util-lib-1.0.zip now and install it using the Install command from the workspace.

Important

To download the ZIP file, right-click the URL > Save link as. The ZIP file will get downloaded to the default download location of your web browser. You must use the 7-Zip utility to extract the contents of the ZIP file, and view the install package components. The contents of the install ZIP file cannot be extracted by using the Windows Zip utility or Mac archive utility.

The goal is to create a Dishes view that will look like this. You can see that we are now able to effectively use the picture and text for the selected restaurant (implied by the dish) and the dish itself.

Clicking on the dish's name brings the user to the Dish view, where the user can immediately order it by providing the few details needed.

Build the Dishes View

Starting with the first view, it is clear that it is a relatively simple list of Dish records, but also shows additional associated information about each one when it is selected.  As usual, let's sketch out a layout for the components before beginning to build it in the tool. Note the three levels of nested containers:  Main (2 columns), with "Details" containing both "Restaurant" / "Dish", each of which have 2 columns also.

The easy part of this is building out the list part, as it involves components we should be familiar with from previous views. 

  1. Create the new view (of layout type Container) and name it Dishes.
  2. Add the "Available Dishes" header using a Rich Text control.
  3. Place a new container below that, with 2 columns; you can set the proportion however you like.
  4. Add the grid on the left side, setting Record Definition Name to Dish.  
    1. Set the Enable Row Selection option to Single row
    2. Configure the columns. 
      1. Consider that the grid will be doing more than just showing visible information: it will also be pulling in data that will not be displayed in the grid, but will be available to be formatted nicely in the rich text controls that will eventually be added to the right hand side.  Also, we take advantage of the ability to include columns from associated records to pull in information about the restaurant.  
      2. Note that large text fields (such as the About fields) will need to have Sorting enabled turned off.
      3. Here is one set of columns that will allow this to be done (if you don't remember how to bring in associated columns, check the documentation or some of the earlier parts of this tutorial). Recall that it is often a good idea to re-label associated fields, such as changing the restaurant's Name column to Restaurant to avoid confusion with the dish Name.

At this point, if you save and preview the view, it should look like this:

Now let's add the single-column "Details" container to the right hand side. Set its Hidden property to be conditional so the container only appears when there is a grid selection.

Now we will add the restaurant information here.

  1. Within the "Details" container, add another Container control with 2 columns (you can use a 5/7 ration for their width); call this the "Restaurant" container.
  2. On the left side, drag in the Display Image component from the palette (it will be there as long as you have installed the Utils library; alternatively, it is also found in the Task Manager Library) and configure it. Note that you will only be able to get the Restaurant ID from the grid if you had previously added it as a hidden column.

  3. On the right side, drag in a Rich Text component and configure it 
    1. Insert an expression using the Edit Expression dialog
    2. Select the Restaurant from the selected row of the grid.

    3. Add static text, and insert an additional expression for About Restaurant, and format to taste.
  4. Save and preview the view, to make sure it is showing a photo and blurb about the restaurant correctly when a dish is selected.

  5. If desired, add another rich text below the "Restaurant" container to create a horizontal rule (you can just use dash characters for this).
  6. Now repeat these steps for the "Dish" container. This time, you will be configuring the photo using the ID from the grid, and About field to get the detailed information. You can also format in the Price of the dish in the same fashion. Remember that you can add any other information about the dish simply by adding it to the grid configuration as a hidden column, and then formatting it using the rich text.

You should now have a fully functioning view. If the containers are nested properly, and the "Details" container has the Hidden condition set properly, the photo and blub will only appear when a dish is selected. If both "Restaurant" and "Dish" containers have the same column ratio (5/7) then the photos and text will also appear to be vertically aligned.

At this point, all the user can do is browse through the dishes. What we want to do, however, is enable the dish Name to be clickable, to bring up a view of the dish for ordering purposes. We will build that view first, then come back and enable the Name column to be clickable.

This is probably a good time to go ahead and add the Dishes view to the application shell, so it appears as menu item. You could call it Menu, because that is how the end user should think of this view.

Now you can test this view in the context of actually running the application. 

The user can browse through dishes, but can't order them yet, so we will turn to adding that functionality next.

The Dish View for Ordering

Let's dive in to creating the second view, in which the dish is displayed and can be ordered. When we are done, it will look like this:

When we think about the information architecture of this view, we can note several challenges that we will have to solve.

  • Information about the dish needs to be displayed right at the top, without the user clicking anything.  We can easily use the same controls to display this as we used in the Dishes view, but one thing we are missing is the dish information itself (the dish ID, description, and price). There are multiple ways to solve this:
    • We could pass all the required parameters in explicitly (ID, description, price, etc). This may make our view harder to re-use in different contexts, however.
    • We could simply pass in the dish ID, because we can use that to load the other Dish fields from that using a record editor in Edit mode.  This is what we do here; furthermore, we will keep this behind-the-scenes record editor within a hidden container, because the end-user does not need to be aware of how we are loading the data.
  • Obviously we will need another record editor for Order, in Create mode - this time, it will be visible for the end-user to use. That's easy to solve. 
  • To complete the experience there will also need to be an association component for adding the Person consumers to the order, exactly as we did in the New Order view.
  • The most complicated thing is the button to send the order. When the user saves the Order record, we will somehow have to associate the order with both the Dish record, as well as the indirectly associated Restaurant record. Let's consider three different approaches to this.
    • We could put back into the view the two association components for Restaurant and Dish; this means asking the user to explicitly re-associate the restaurant and dish before saving. But this would be a terrible experience, since they have already selected the dish they want before coming to this view; it defeats the main design purpose of this view.
    • We could have a rule configured to run "On Create" of the Order record and have it do the associations for us. This will work, but will get pretty messy. The problem here is that the process needs to know the dish ID in order to do this, and the only way to pass information like that to this process would be to place it in a temporary field before creating it. This wastes database storage. Also, it would mean accessing the system field that keeps the foreign key of the restaurant; not something the UI logic is supposed to be playing with.
    • The cleanest way to solve this, and what we will do here, is create a special process to perform the association. Rather than trigger it from a rule such as "On Create", which would require a temporary field to pass the dish ID, we can use the Launch Process action right from the same button that saves the Order record. Since we already have the Dish ID available in our view, we just pass it directly to the process to create the necessary associations. Don't worry if this is not yet completely clear; there will be a complete explanation of this technique when we get there in the step-by-step instructions.

Given these design decisions, we can sketch the layout of components that we will need to make this view successful.

Displaying Dish Information

The first thing we should do is make sure the Dish record is loaded up when the view is shown.  For this we will need to create a view Input Parameter - we will call it Dish ID.

Add the "Info" and "Hidden" containers.


Drag in a record editor to the "Hidden" container, set it to Edit mode, and bind it the Dish record definition, where the Record ID is set to the Dish ID view input parameter. You will need to add the required fields. Remember, the only purpose of this record editor is to load the dish details when the view loads, so they can be referenced in the "Info" section. You can almost think of this components as the "model" of the dish data within this "view".

Now we can configure the "Info" contents, which are going to be visible. 

  1. Make sure it has 2 columns.
  2. On the left side, add a Rich Text component.
    1. Insert an expression for the dish name, and style it as desired.
    2. Insert an expression
    3. Grab the Dish Name

    4. Style the name
    5. Do the same thing for the description about the dish, and price.
  3. On the right side, add the Display Image component and configure it, just we did for the Dishes view earlier.

At this point, you can save and preview the view. Note that you will be prompted for a valid Dish ID, which you can obtain using the Edit Data feature from the list of record definitions.

At this point you should be able to see the information about the dish.  If you are also seeing the record editor at the bottom of the view, it is probably because you did not yet mark the Hidden attribute of the container as At all Times.

Hint: once you have a preview browser tab for this, the URL contains the parameter directly. So, if you keep this tab around, you can simply refresh it when you want to try the latest definition, without having to launch it from Preview again and paste in a Dish ID.

Placing the Order

Now we need to provide a way for the end user to order the dish. We essentially follow similar steps to those used to create the New Order view - with two major differences.

  • We will not need to ask the user to specify the Restaurant or Dish - the view already has that information.
  • We will need to build out some special logic to associate the new Order with the dish and its restaurant, using a small helper process.

Between the existing containers "Info" and "Hidden", place a record editor component for the Order record in Create mode, and follow the similar steps as before to create the rich text label, get the requested date, and the associated persons.

One easy way to build this out is the following sequence of steps:

  1. Bring in the Record Editor
  2. Drag in a Container component into the top part of the Record Editor component itself, and set it to 2 columns. If you want to name this, you could call it "Order Fields".
  3. Drag in the Rich Text on the left side for the "Order it Now!" label.
  4. Below that, drag in a Date component.
  5. On the right side, drag in a Text Area component.
  6. Below the text area, drag in an Association component.
  7. Drag in a Button Bar, and then a Button, within the record editor area but below the Container.

Now you can complete the configuration by binding the fields for Requested Date and Special Instructions.

Just as we did in the New Order view, configure the associations for Person (remember, you will find this record and view name in the Foundation, not in this application).

Give the button the label Save. At this point, the layout for the order record definition looks like this:

To configure the button, however, will require a power technique of creating a special process to be invoked by the view.

Creating the Logic to Save and Associate the Order

Let's consider the button actions we will need. We can start by configuring the regular Save action for the Order, as we did with the New Order view previously. Make sure you pick the right record editor to save (there are two)!


Is this enough? Well, it will accomplish part of what needs to be done - saving the order. However, if you try out your new view, you may notice something is missing from the data - the associations to it's dish and restaurant.

On the one hand, we have made the UI simpler for the end-user because they do not have to pick the restaurant, or dish, within this view. On the other hand, the associations are important and still need to be created. How can this be automated so that the user does not have to specify it explicitly?

The answer is that we can create a small process - like a kind of script that we can triggered from the Save button itself - using the Process Designer. The process will take the Dish ID and the Order ID as input variables (parameters) and use these to accomplish this. It will also be necessary to load the Dish record into a local variable in order to access its Restaurant information. The following diagram illustrates the logic of this process - remember that you can click on it to make it more readable.

We can now build out this process, following these explicit steps.

  1. Back in the workspace, go to the Processes tab and click New.
  2. Give the process some name, such as "Associate Dish and Restaurant to Order"
  3. Add three variables to the process
    1. Click the Add / Remove Variables button.
    2. Add an input parameter for Dish ID.
    3. Add another one for Order ID.
    4. We will also need another Local Variable that will be used to load all the information about the Dish (in order to access its associations). It will be used only during the execution of the process. Let's declare that now. Note that it is not an Input/Output Variable, and its Data Type must be set to Record, and the record definition is Dish.
    5. Once you save the variables, the process properties tab will now show a summary of your variables, which should look like this:
  4. Associate the Dish to the Order
    1. Drag in the Associate Records activity from the palette.
    2. Give the activity a more descriptive name, and select the appropriate association.
    3. Using the Edit Expression dialog, select the Dish ID input parameter as the value for First Record ID.
    4. Similarly, set the Order ID input parameter value as the Second Record ID.
  5. Load the dish record
    1. Drag in a Get Record activity and configure it to load the Dish based on the Dish ID input parameter.
    2. Configure the OUTPUT MAP of the activity to set the Dish local variable. 
    3. Use the Output of the activity as the value for the Source expression. This works because the output of Get Record is always a full record object.
    4. The configuration of Get Record is now done, and the summary should look as follows:
  6. Associate the restaurant to the order.
    1. Drag in another Associate Records activity.
    2. This time, to get the First Record ID, we will have to find the restaurant ID by looking in the associations of our Dish local variable. Note that this only works because we placed the Dish variable in the OUTPUT MAP of the Get Record earlier.


    3. As before, the Second Record ID is the input parameter Order ID.

  7. .Add the four flows to connect the activities.
  8. Save. If you have any validation errors you will need to fix this and make sure all the configurations are correct.

Now that the process is done, it would be a good idea to test it, independently of the view that will be invoking it. One easy way to do this is as follows:

  1. Manually create an Order record, using the Edit Data feature.
    1. Take note of its ID field value, for example, paste it into a notepad.
    2. Verify that the order exists in the Orders view, and has no associations.
  2. Similarly take note of an existing Dish record's ID field value, using the Edit Data feature.
  3. In the Processes tab of the workspace, click on Manage Processes button.
  4. Select your new process and click Run.
  5. Provide the Order ID and Dish ID parameters when prompted.
  6. Click the Run button.
    1. If the process completes successfully, check the Orders view to see if the order now shows the correct dish and restaurant.
    2. If it fails to run, the message may help you identify the problem in your process definition.

Finishing Up

 First, we should integrate the new process with the Save button in the Dish view. 

  1. Add a Launch Process action to its action list, after the Save action.
  2. Set the Process to Start and turn on Wait for Process Completion.
  3. Configure the Order ID parameter by getting it from the record editor for the new order (the ID field value is set implicitly by the Save action, as long as it runs after the Save action).
  4. Configure the Dish ID parameter using the view's input parameter for Dish ID.

You should also add a final action to this button, to cause it to navigate to the Orders view. Presumably the user is done with this view after placing the order.

Save the view.

At this point you can test out the full behavior of the view, using Preview, or go ahead and integrate it with the Dishes view.

To add the hyperlink to the Name column of the grid of dishes:

  1. Open the Dishes view.
  2. Select the grid of dishes.
  3. Click on Add/Remove Grid Columns.
  4. Open the properties for the Name column
  5. Turn on Make column value an Action Button.
  6. Click Add/Remove Actions. In the Selected Actions list, and configure the link as an Open View action. Note that the ID column must be present in the grid (it is normally hidden from users). Be sure to pick it from the Last Action Row, not First Selected Row, because treating a value as a link does not involve selection.

    The tooltip will confirm you got the right ID.

  7. Save and test the Dishes view using Preview or by using the shell, including the behavior of ordering a dish.

What we Learned

Creating this view was loaded with power techniques, and also was a good review of many of the view-building strategies we learned earlier.

  • Designing complex views starting from sketches, and then laying out the nested containers.
  • Using attachment field values to display dynamic images in the view.
  • Views with input parameters are not only for modal popups and blades.
  • Using rich text to format information in a nice way, with the model loaded in a hidden record editor.
  • By the use of the Launch Process action, and the Process Designer, sophisticated logic can be invoked directly from the view, without using rules to run processes. This can significantly improve user experience without requiring the use of custom UI code.

We have had a little taste of using the Process Designer just to add a little bit of functionality to a view. Now we will dive into it much more deeply in order to build out the back-end lifecycle process for a lunch order.


Was this page helpful? Yes No Submitting... Thank you

Comments