Introduction: Creating a Web Form in Wolfram Language

This is an exercise to create a Web Form using Wolfram Language. Though the explanation is using an example, "Energy Efficiency Calculator", we can use the functions used for generating any type of webform.

To do this, we need to first figure out the role of each function we need - CreateDatabin[], FormObject[] and various options to change the appearance of the Webform.

Finally, we put everything together and let the users enter their responses using FormFunction[] and deploy it using CloudDeploy[].

Let's move to Step 1!!!

Step 1: Connect to the Wolfram Cloud!

We can do this by using the CloudConnect[] function. This shows a dialog to input both the username and password if you haven't connect to the Wolfram Cloud. An Image of the code with its output is shown.

Code:

CloudConnect[]

Step 2: Create a Place to Store Your Data

The CreateDatabin[] funciton lets you create a databin in the Wolfram Data Drop where all your data will be stored and returns the corresponding Databin object. While using this function, we need to define what all goes into the Databin as well as its name and permissions. An example Databin for the Energy Efficiency Calculator is shown. It shows the list of data with its data types.

Code

energyEfficiency =
CreateDatabin[<|"Name" -> "Energy Efficiency Calculator", Permissions -> "Public", "Interpretation" -> { "thermostat" -> "Integer", "insulation" -> "Integer", "lighting" -> "Integer", "energyStar" -> "Integer", "fridge" -> "Integer", "draftyWindows" -> "Integer", "aerators" -> "Integer", "lowFlow" -> "Integer", "shade" -> "Integer", "insDucts" -> "Integer"}|>]

Step 3: Make Your Form Object, the Integral Part of Your Webform

The Webform is made up Form Objects. This defines what all constitute each row of the form along with its layout. The layout of the form can be defined by the FormLayoutFunction[] where the title, description and other Appearance rules can be defined. More about Appearance rules can be found at http://reference.wolfram.com/language/ref/Appeara...

The first part "fo" denotes the Form Object which we will be defining in the second line of code.

Note that we have defined our Form layout with a delayed evaluation (:= denotes delayed evaluation). This tells the program that the values for the Form Object will be input later (in this case, in the next line of code). Also, note that we have defined our Form Object to fo which has a delayed evaluation (:= denotes delayed evaluation). This tells the program that the values for the Webform would be input by the user later. We don't have to do this but this makes the code a lot cleaner moving forward as we will be adding more and more functions. Because of the delayed evaluation, this line of code will not have an output.

Code:

layout[fo_FormObject] := Column[{fo[AppearanceRules, "Title"], fo[AppearanceRules, "Description"], Grid[Values@Merge[{fo[All, "Label"], fo[All, "Control"]}, Identity], Alignment -> Left]}];

fo := FormObject[<|"thermostat" -> <|"Interpreter" -> {"Yes" -> 10, "No" -> 1}, "Control" -> RadioButtonBar, "Label" -> "Do you have a programmable thermostat?"|>, "insulation" -> <|"Interpreter" -> {"Yes" -> 10, "No" -> 1, "Maybe" -> 5}, "Control" -> RadioButtonBar, "Label" -> "Is your house well-insulated?"|>, "lighting" -> <|"Interpreter" -> {"Most/All" -> 10, "Around half" -> 5, "Very few/None" -> 1}, "Control" -> RadioButtonBar, "Label" -> "What percentage of the lighting is CFL?"|>, "energyStar" -> <|"Interpreter" -> {"Yes" -> 10, "No" -> 1}, "Control" -> RadioButtonBar, "Label" -> "Are the appliances energyStar certified?"|>, "fridge" -> <|"Interpreter" -> {"1" -> 10, "2" -> 5, "3" -> 1}, "Control" -> RadioButtonBar, "Label" -> "How many refrigerators do you have?"|>, "draftyWindows" -> <|"Interpreter" -> {"Yes" -> 1, "No" -> 10, "Maybe" -> 5}, "Control" -> RadioButtonBar, "Label" -> "Does the house have drafty windows?"|>, "aerators" -> <|"Interpreter" -> {"Yes" -> 10, "No" -> 1}, "Control" -> RadioButtonBar, "Label" -> "Do the faucets have aerators?"|>, "lowFlow" -> <|"Interpreter" -> {"Yes" -> 10, "No" -> 1}, "Control" -> RadioButtonBar, "Label" -> "Are the showers low-flow?"|>, "shade" -> <|"Interpreter" -> {"Yes" -> 10, "No" -> 1}, "Control" -> RadioButtonBar, "Label" -> "Does the house have shrubs and trees for shade?"|>, "insDucts" -> <|"Interpreter" -> {"Yes" -> 10, "No" -> 1}, "Control" -> RadioButtonBar, "Label" -> "Are the heating ducts in the non-heated areas insulated?"|>|>, AppearanceRules -> <|"Title" -> "Take the Energy Efficiency Quiz.", "Description" -> "A score higher than 70 is energy efficient!", "SubmitLabel" -> "Calculate" |>, FormLayoutFunction -> layout]

Step 4: Add Data to Your Databin

When the Webform is deployed, DatabinAdd[] function is used to denote what are the elements that are being added to your Databin. For the example shown, we will be assigning test values but the actual command will have to take the inputs from the user. TextString[] converts the final score to a string that is evaluated by adding all the values in the energyEfficiency Databin. The error return value "-1" has also been defined.

Code:

DatabinAdd[energyEfficiency, <|"thermostat" -> 10, "insulation" -> 10, "lighting" -> 10, "energyStar" -> 10, "fridge" -> 5, "draftyWindows" -> 5, "aerators" -> 10, "lowFlow" -> 1, "shade" -> 1, "insDucts" -> 10|>]; "Thank you for submitting your efficiency ratings! Your Energy Efficiency score is: " <> TextString[Total[Values[energyEfficiency]][[-1]]]

Step 5: The FormFunction[]

Now for the user to input the values, we use the FormFunction[]. Let's break this line of code down.

The first part "fo" denotes the Form Object which we had defined earlier.

The second part includes the DatabinAdd function which defines the data that needs to be added to our Databin, "energyEfficiency". We have used "#" i.e. a slot right before the variables that were defined in the Form Object as well as the Databin. This tells the program that the code is referring to the same variable in the program.

After that, Rasterize[], Style[] functions with FontSize and FontFamily are used to change the Style of the output. "PNG" means that the final output will be a picture in the PNG format.

Finally, we have the last part which sets the theme of the form using FormTheme. More options for FormTheme can be found here - http://reference.wolfram.com/language/ref/FormThe....

Please note that we have put all this into our defined function, "formFunc" with delayed evaluation (using :=) so that the code for the final line will be easier to understand. Because of the delayed evaluation, this line of code will not have an output.

Code:

formFunc := FormFunction[fo, (DatabinAdd [energyEfficiency, <|"thermostat" -> #thermostat, "insulation" -> #insulation, "lighting" -> #lighting, "energyStar" -> #energyStar, "fridge" -> #fridge, "draftyWindows" -> #draftyWindows, "aerators" -> #aerators, "lowFlow" -> #lowFlow, "shade" -> #shade, "insDucts" -> #insDucts|>]; Rasterize [Style ["Thank you for submitting your efficiency ratings! Your \ Energy Efficiency score is: " <> TextString[Total[Values[energyEfficiency]][[-1]]], FontSize -> 20, FontFamily -> "Aparajita"]]) &, "PNG", FormTheme -> "Blue" ]

Step 6: Deploying to the Cloud

Lastly, we will deploy the program to the cloud using CloudDeploy[] so that you can run it in any web browser.

We have put all the things we want in the FormFunction[] into formFunc.

The first part of CloudDeploy evaluates this. Next is the name of the cloud program we have deployed which will be there in the link you get after you evaluate this line of code. Finally, we set the Permissions to Public so that anyone who has clicked the link can evaluate the program.

Code:

CloudDeploy[formFunc, "EnergyEfficiencyForm", Permissions -> "Public"]

Step 7: That's It! Now You Can Generate Any Webform Using Wolfram Language and Evaluate the Output As Well!

The following link will take you to the Wolfram Development Platform for this example. You can tinker around and make your own awesome web forms after signing in!

https://wolfr.am/7sWktv6a

In case you're wondering how the program would've looked without using functions we defined, here it is! Its long but going through it carefully, we can see what each part of the code is doing.

Code:

energyEfficiency = CreateDatabin[<|"Name" -> "Energy Efficiency Calculator", Permissions -> "Public", "Interpretation" -> { "thermostat" -> "Integer", "insulation" -> "Integer", "lighting" -> "Integer", "energyStar" -> "Integer", "fridge" -> "Integer", "draftyWindows" -> "Integer", "aerators" -> "Integer", "lowFlow" -> "Integer", "shade" -> "Integer", "insDucts" -> "Integer"}|>]

layout[fo_FormObject] := Column[{fo[AppearanceRules, "Title"], fo[AppearanceRules, "Description"], Grid[Values@Merge[{fo[All, "Label"], fo[All, "Control"]}, Identity], Alignment -> Left]}];

CloudDeploy [FormFunction [FormObject[<|"thermostat" -> <|"Interpreter" -> {"Yes" -> 10, "No" -> 1}, "Control" -> RadioButtonBar, "Label" -> "Do you have a programmable thermostat?"|>, "insulation" -> <| "Interpreter" -> {"Yes" -> 10, "No" -> 1, "Maybe" -> 5}, "Control" -> RadioButtonBar, "Label" -> "Is your house well-insulated?"|>, "lighting" -> <|"Interpreter" -> {"Most/All" -> 10, "Around half" -> 5, "Very few/None" -> 1}, "Control" -> RadioButtonBar, "Label" -> "What percentage of the lighting is CFL?"|>, "energyStar" -> <|"Interpreter" -> {"Yes" -> 10, "No" -> 1}, "Control" -> RadioButtonBar, "Label" -> "Are the appliances energyStar certified?"|>, "fridge" -> <|"Interpreter" -> {"1" -> 10, "2" -> 5, "3" -> 1}, "Control" -> RadioButtonBar, "Label" -> "How many refrigerators do you have?"|>, "draftyWindows" -> <|"Interpreter" -> {"Yes" -> 1, "No" -> 10, "Maybe" -> 5}, "Control" -> RadioButtonBar, "Label" -> "Does the house have drafty windows?"|>, "aerators" -> <|"Interpreter" -> {"Yes" -> 10, "No" -> 1}, "Control" -> RadioButtonBar, "Label" -> "Do the faucets have aerators?"|>, "lowFlow" -> <|"Interpreter" -> {"Yes" -> 10, "No" -> 1}, "Control" -> RadioButtonBar, "Label" -> "Are the showers low-flow?"|>, "shade" -> <|"Interpreter" -> {"Yes" -> 10, "No" -> 1}, "Control" -> RadioButtonBar, "Label" -> "Does the house have shrubs and trees for shade?"|>, "insDucts" -> <|"Interpreter" -> {"Yes" -> 10, "No" -> 1}, "Control" -> RadioButtonBar, "Label" -> "Are the heating ducts in the non-heated areas insulated?"|>|>, AppearanceRules -> <|"Title" -> "Take the Energy Efficiency Quiz.", "Description" -> "A score higher than 70 is energy efficient!", "SubmitLabel" -> "Calculate" |>, FormLayoutFunction -> layout], (DatabinAdd [energyEfficiency, <|"thermostat" -> #thermostat, "insulation" -> #insulation, "lighting" -> #lighting, "energyStar" -> #energyStar, "fridge" -> #fridge, "draftyWindows" -> #draftyWindows, "aerators" -> #aerators, "lowFlow" -> #lowFlow, "shade" -> #shade, "insDucts" -> #insDucts|>]; Rasterize[Style["Thank you for submitting your efficiency ratings! Your Energy Efficiency score is: " <> TextString[Total[Values[energyEfficiency]][[-1]]], FontSize -> 20, FontFamily -> "Aparajita"]]) &, "PNG", FormTheme -> "Blue" ], "energyEfficiencyWorkingCopy", Permissions -> "Public"]