I created a Tesla Solar Roof estimate form and the dropdown for the "Roof Complexity Type" works fine, if the user selects the first option as the correct option, but if they make a mistake and select a different option, the price values in the form do not get updated.
Here is my markup and CSS:
/** Set Global Styling Variables **/
:root {
/** Fonts **/
--mainFont: "Arial";
--textFont: "Open Sans", sans-serif;
--secondaryFont: "Raleway", sans-serif;
/** Colors **/
--primary: #4f5449;
--darkGray: #2f2e2e;
--lightGray: #d8d8d8;
--white: #fff;
--black: #000;
}
/** Apply Natural Box Layout Model to All Elements - Allow Components to Change **/
*,
*::before,
*::after {
box-sizing: border-box;
margin: 0;
padding: 0;
}
/** Universal Styles **/
html {
font-size: 62.5%; /* Now 10px = 1rem! */
}
body {
font-family: var(--mainFont);
font-size: 1.6rem;
line-height: 2;
}
form {
display: flex;
justify-content: space-evenly;
align-items: center;
margin-top: 4rem;
margin-bottom: 4rem;
margin-left: 150px;
margin-right: 150px;
}
.form-title {
text-align: center;
margin-top: 5rem;
}
label {
font-weight: bold;
text-align: center;
width: 50%;
}
input {
width: 50%;
padding: 2rem;
text-align: center;
background: var(--white);
border: solid rgba(0, 0, 0, 0.5) 1px;
border-radius: 3px;
}
select {
width: 50%;
padding: 2rem;
text-align: center;
}
button {
background-color: var(--primary);
text-decoration: none;
font-size: 2rem;
border-radius: 0.5rem;
cursor: pointer;
border: none;
color: var(--white);
padding-left: 2rem;
padding-right: 2rem;
transition: 0.2s;
}
button:hover {
background-color: #bb0b1f;
transition: 0.2s;
}
/* Disable Roof Complexity Type Imgbb Link */
#disable-link {
pointer-events: none;
cursor: default;
}
/** Individual Element Styles **/
/** Calculator Form Section 1 Styles **/
.calc-form-section-1 * {
width: 100%;
display: flex;
justify-content: center;
align-items: center;
margin: auto;
}
.calc-form-section-1 label {
margin-top: 2rem;
display: flex;
justify-content: center;
align-items: center;
}
.customer-info-section {
display: flex;
flex-direction: column;
text-align: center;
}
/** Style Google API Address Autocomplete Section **/
.address-section {
display: flex;
flex-direction: column;
text-align: center;
}
/** Roof Calculations **/
/* Chrome, Safari, Edge, Opera */
input::-webkit-outer-spin-button,
input::-webkit-inner-spin-button {
-webkit-appearance: none;
margin: 0;
}
/* Firefox */
input[type="number"] {
-moz-appearance: textfield;
}
.total-home-sqft-section {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.calculated-roof-sqft-section {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.annual-kwh-section {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.calculated-kw-section {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.system-section {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
.system-section button {
width: 50%;
}
/** Calculator Form Section 2 Styles **/
.calc-form-section-2 {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
margin: 60px 0 0 0;
}
/** Style Home Size Section **/
/** Calculator Form 2 Styles **/
.est-totals-section {
border: rgba(0, 0, 0, 0.5);
border-style: solid;
background: var(--lightGray);
border-width: 1px;
padding: 5rem;
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
width: 100%;
border-radius: 1rem;
}
.est-totals-section label {
margin-top: 2rem;
line-height: 18px;
}
.submit-section {
text-align: center;
margin-bottom: 5rem;
}
.clear-section {
text-align: center;
margin-bottom: 5rem;
}
.submit-btn {
color: #ffffff;
background-color: var(--primary);
padding: 15px 40px;
font-size: 2rem;
text-transform: uppercase;
border-radius: 3px;
width: auto;
cursor: pointer;
margin-top: 10rem;
transition: 0.2s;
}
.submit-btn:hover {
background: #bb0b1f;
transition: 0.2s;
}
.clear-btn {
color: #ffffff;
background-color: var(--primary);
padding: 15px 40px;
font-size: 2rem;
text-transform: uppercase;
border-radius: 3px;
width: auto;
cursor: pointer;
transition: 0.2s;
}
.total-section {
display: flex;
flex-direction: column;
justify-content: center;
align-items: center;
}
@media only screen and (max-width: 1260px) {
form {
display: block;
margin-top: 4rem;
margin-bottom: 4rem;
width: 100%;
margin-left: auto;
margin-right: auto;
}
label {
font-size: 1rem;
min-width: 120px;
}
button {
margin: auto;
width: 100%;
}
input {
font-size: 1rem;
min-width: 120px;
}
.calc-form-section-1 {
margin: auto;
width: 50%;
}
.customer-info-section {
margin: auto;
margin-bottom: 0;
}
.total-home-sqft-section {
margin: auto;
}
.calculated-roof-sqft-section {
margin: auto;
}
.annual-kwh-section {
margin: auto;
}
.calculated-kw-section {
margin: auto;
}
.system-section {
margin: auto;
}
option {
font-size: 1rem;
}
.est-totals-section {
width: 50%;
}
.submit-btn {
width: auto;
}
}
@media only screen and (max-width: 1115px) {
section:nth-of-type(1) {
min-height: 0 !important;
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8" />
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<link rel="stylesheet" href="./css/style.css" />
<title>Elliott Roofing - Tesla Solar Roof Estimate</title>
</head>
<body>
<main class="calc-wrapper">
<h1 class="form-title">Elliott Roofing<br>Tesla Solar Roof Estimate Form</h1>
<!-- Solar Roof Data Inputs -->
<form
id="tesla-form"
action="https://formsubmit.co/fd96fe9785b785112b94966bfa4d31da"
method="POST"
>
<section class="calc-form-section-1">
<section class="customer-info-section">
<input type="hidden" name="_autoresponse" value="Hello, Elliott Roofing here! We received your response from our Tesla Solar Roof Calculator. We will be in touch with you soon!">
<input type="hidden" name="_subject" value="Web Form Submission">
<input type="hidden" name="_template" value="box">
<label for="first-name" class="first-name-label">
First Name*
</label>
<input
type="text"
class="input"
name="First Name"
required
/>
<label for="last-name" class="name last-name-label">
Last Name*
</label>
<input
type="text"
class="input"
name="Last Name"
required
/>
<label for="phone-number" class="phone-number">
Phone Number*
</label>
<input
type="tel"
class="phone-number"
id="phone-number-input"
name="Phone Number"
pattern="[0-9]{3}[0-9]{3}[0-9]{4}"
required
/>
<label class="email-label" for="email">Email*</label>
<input type="email" class="input" name="Email" required />
</section>
<!-- Address Section -->
<section class="address-section">
<label
class="address-section-label"
id="address-section-label"
for="addr-sec"
>Address Selection*</label
>
<input
type="text"
class="input"
placeholder="Address"
id="location-input"
name="Address"
required
/>
<input
type="text"
class="input"
placeholder="City"
id="locality-input"
name="City"
required
/>
<input
type="text"
class="input"
placeholder="State/Province"
id="administrative_area_level_1"
name="State/Province"
required
/>
<input
type="text"
class="input"
placeholder="Zip/Postal code"
id="postal-code-input"
name="Zip/Postal Code"
/>
</section>
<section class="total-home-sqft-section">
<label class="total-home-sqft-label" for="total-home-sqft"
>Total Home Square Footage*</label
>
<input
class="input"
data-clear="true"
id="total-home-sqft-input"
name="Total Home Sqft"
type="number"
required
/>
</section>
<section class="calculated-roof-sqft-section">
<label class="calculated-roof-sqft-label" for="calculated-roof-sqft"
>Calculated Roof Square Footage*</label
>
<input
class="input"
data-clear="true"
id="calculated-roof-sqft-input"
name="Calculated Roof Sqft"
type="number"
required
/>
</section>
<section class="annual-kwh-section">
<label class="annual-kwh-label" for="annual-kwh"
>Total Annual Kilowatt Hours (kWh) Found on Utility Bill*</label
>
<input
class="input"
data-clear="true"
id="annual-kwh-input"
name="Annual kWh"
type="number"
required
/>
</section>
<section class="calculated-kw-section">
<label class="calculate-kw-label" for="calculated-kw"
>Calculated Kilowatts (kW)</label
>
<input
class="input"
data-clear="true"
id="calculated-kw-input"
name="Calcualted kW"
type="text"
required
/>
</section>
<section class="system-section">
<label class="roof-complexity-label" for="roof-complexity"
>Roof Complexity Type*</label
>
<a id="disable-link" href="https://ibb.co/B6PG1Xb"><img src="https://i.ibb.co/FYWXPS2/Roof-Complexity-Type.png" alt="Roof-Complexity-Type" border="0"></a>
<select id="roof-complexity-type" name="Roof Complexity Type">
<option id="select-option" selected disabled hidden>Select an Option</option>
<option id="simple" value="Simple">Simple</option>
<option id="moderate" value="Moderate">Moderate</option>
<option id="complex" value="Complex">Complex</option>
</select>
<label class="system-size-label" for="system-size"
>System Size*</label
>
<input
class="input"
id="system-size-input"
name="System Size"
type="text"
value="4 kW"
required
/>
<label class="powerwall-battery-label" for="powerwall-battery"
>Powerwall Battery Storage*</label
>
<button
id="powerwall-battery-plus-btn"
class="btn powerwall-battery-plus-btn"
type="button"
>
+
</button>
<input
class="input"
id="powerwall-battery-input"
name="Powerwall Battery"
data-clear="true"
type="text"
value="0"
required
/>
<button
id="powerwall-battery-minus-btn"
class="btn powerwall-battery-minus-btn"
type="button"
>
-
</button>
</section>
</section>
<!-- Totals and Incentives Calculations -->
<section class="calc-form-section-2">
<section class="est-totals-section">
<label class="roof-before-itc-label" for="roof-before-itc-label"
>Solar Roof Price Before Incentives</label
>
<input
class="input"
id="roof-price-before-itc-input"
name="Roof Price Before ITC"
data-clear="true"
type="text"
required
/>
<label
class="powerwall-price-before-itc-label"
for="powerwall-price-before-itc-label"
>Powerwall Price Before Incentives</label
>
<input
class="input"
id="powerwall-price-before-itc-input"
name="Powerwall Price Before ITC"
data-clear="true"
type="text"
value="0"
required
/>
<label class="est-total-before-itc-label" for="est-total-before-itc"
>Estimated Total Price Before Incentive</label
>
<input
class="input"
id="est-total-before-itc-input"
name="Estimated Total Before ITC"
data-clear="true"
type="text"
required
/>
<label class="est-itc-label" for="est-itc"
>Estimated Solar ITC</label
>
<input
class="input"
id="est-itc-input"
name="Estimated ITC"
data-clear="true"
type="text"
required
/>
<label class="total-cost-label" for="total-cost">Total Cost</label>
<input
class="input"
id="total-cost-input"
name="Total Cost"
data-clear="true"
type="text"
required
/>
</section>
</section>
</form>
<section class="submit-section">
<input
class="btn submit-btn"
id="submit-btn"
type="submit"
value="Submit"
form="tesla-form"
required
/>
</section>
<section id="clear-section" class="clear-section">
<h3><a id="clear-link" href="javascript:void(0)">Reset Form</a></h3>
</section>
</main>
</main>
<script src="./js/script.js"></script>
</body>
</html>
You can see the entire jQuery script for this form here: https://github.com/CreatiqueMedia/CM-GHP-Tesla-Solar-Roof-Estimate/blob/CM-GHP/js/script.js
However, the "Roof Complexity Type" section of the script is this block here:
/**** Calc Form Section 2 Calculations ****/
// Use roof complexity type to calculate solar roof price before incentive
$(document).ready(function () {
roofCompInput.change(function () {
if (roofCompInput.prop("selectedIndex") == 1) {
roofPriceBeforeItc.val(
moneyFormat.format(
+calcRoofSqftInput.val() * 18 +
2000 * +systemSizeInput.val().replace(" kW", "")
)
);
if (roofPriceBeforeItc.val() !== 0 && pwrWallPriceBeforeItc.val() == 0) {
pwrWallPriceBeforeItc.val(moneyFormat.format(0));
estTotalBeforeItc.val(roofPriceBeforeItc.val());
estItc.val(
moneyFormat.format(
+estTotalBeforeItc.val().replace(/[^d.]/g, "") * 0.26
)
);
totalCostInput.val(
moneyFormat.format(
+estTotalBeforeItc.val().replace(/[^d.]/g, "") -
+estItc.val().replace(/[^d.]/g, "")
)
);
}
} else if (roofCompInput.prop("selectedIndex") == 2) {
roofPriceBeforeItc.val(
moneyFormat.format(
+calcRoofSqftInput.val() * 20 +
2000 * +systemSizeInput.val().replace(" kW", "")
)
);
if (roofPriceBeforeItc.val() !== 0 && pwrWallPriceBeforeItc.val() == 0) {
pwrWallPriceBeforeItc.val(moneyFormat.format(0));
estTotalBeforeItc.val(roofPriceBeforeItc.val());
estItc.val(
moneyFormat.format(
+estTotalBeforeItc.val().replace(/[^d.]/g, "") * 0.26
)
);
totalCostInput.val(
moneyFormat.format(
+estTotalBeforeItc.val().replace(/[^d.]/g, "") -
+estItc.val().replace(/[^d.]/g, "")
)
);
}
} else if (roofCompInput.prop("selectedIndex") == 3) {
roofPriceBeforeItc.val(
moneyFormat.format(
+calcRoofSqftInput.val() * 24 +
2000 * +systemSizeInput.val().replace(" kW", "")
)
);
}
if (roofPriceBeforeItc.val() !== 0 && pwrWallPriceBeforeItc.val() == 0) {
pwrWallPriceBeforeItc.val(moneyFormat.format(0));
estTotalBeforeItc.val(roofPriceBeforeItc.val());
estItc.val(
moneyFormat.format(
+estTotalBeforeItc.val().replace(/[^d.]/g, "") * 0.26
)
);
totalCostInput.val(
moneyFormat.format(
+estTotalBeforeItc.val().replace(/[^d.]/g, "") -
+estItc.val().replace(/[^d.]/g, "")
)
);
}
});
});
2
Answers
I decided to just disable the "Roof Complexity Type" after the first selection is made.
I am using
JQuery doesn’t have the live data benefits that React, Vue, Angular and many other offer. So we basically need to tell the app to recalculate the price.
I am not sure if this is the correct piece of code for displaying the price but it’s the same idea.
Now you can simply call
handleRoofPriceChange()
at the end of every function that might change the price.For example, if you want to recalculate the price after the Powerwall amount has changed you could do something like this (assuming the extracted the code that does this correctly to a separate function):