Dynamic Forms with Webflow CMS

hey all.

I’m trying to create an Apple.com-like “configure” experience to my forms.

Here’s my problem: My company is a platform that allows designers to sell packaged design services.The whole concept hinges on the fact that “configuration” replaces traditional negotiating.

Every designer is able to offer sub-services as “up-sells” to the primary service. The user is able to select between these up-sells, much like configuring a macbook.

Here is the Apple page I’d like to emulate: https://www.apple.com/us_smb_78313/shop/buy-mac/macbook-pro?product=MPXT2LL/A&step=config#

Anybody know to update these forms via the CMS?


Here is my public share link: https://preview.webflow.com/preview/designcue?preview=8e8175a5a42962d8cda37d309eaf56d2

1 Like

At this time, Webflow doesn’t have a native way to create dynamic forms. But, you might be able to do it with custom code. I’ve built this in the past with Webflow and custom code:

http://dropdowns.webflow.io/
http://teslamotors.webflow.io/designer-tool-v2

3 Likes

How did you get the price to update with the selections?

1 Like

a bunch of javascript :wink:

	var tmsLease = 0,
		tmsLoan = 0,
		tmsCash = 0,
		leaseTotal = 0,
		loanTotal = 0,
		cashTotal = 0,
		stepCount = ($('.tms-step').length) + 1,
		optionLeaseNew = {},
		optionLeasePrev = {},
		optionLoanNew = {},
		optionLoanPrev = {},
		optionCashNew = {},
		optionCashPrev = {},
		nextStep = 0,
		color = 'black-bg',
		newColor = '',
		$customizer = $('div.customizer');

	for ( var i = 0; i < stepCount; i++ ) {
		optionLeaseNew[i] = 0
		optionLeasePrev[i] = 0
		optionLoanNew[i] = 0
		optionLoanPrev[i] = 0
		optionCashNew[i] = 0
		optionCashPrev[i] = 0
	}
	
	$('.lease-total span').text(commaNumber(tmsLease))
	$('.loan-total span').text(commaNumber(tmsLoan))
	$('.cash-total span').text(commaNumber(tmsCash))

	$('.tms-start .tms-selection').click(function(){

		tmsLease = 0
		tmsLoan = 0
		tmsCash = 0
		leaseTotal = 0
		loanTotal = 0
		cashTotal = 0

		tmsLease = parseInt($(this).attr('data-lease'))
		tmsLoan = parseInt($(this).attr('data-loan'))
		tmsCash = parseInt($(this).attr('data-cash'))

		leaseTotal = tmsLease
		loanTotal = tmsLoan
		cashTotal = tmsCash

		$('.lease-total span').text(commaNumber(leaseTotal))
		$('.loan-total span').text(commaNumber(loanTotal))
		$('.cash-total span').text(commaNumber(cashTotal))
		
		$('.tms-start .tms-selection').removeClass('selected')

		$(this).addClass('selected')

		$('.tms-step').hide()
		nextStep = $(this).attr('data-next')
		$($('.tms-step[data-step=' + nextStep + ']')).fadeIn('slow')

		// Calculate top position of the outer node and the step we want to scroll to
		var customizerTop = $customizer.offset().top;
		var stepTop = $('.tms-step[data-step=' + nextStep + ']').offset().top;

		// Calculate pixel difference pixels between outer node and the next step
		var scrollDiff = stepTop - customizerTop;

		// Apply the difference to the current scroll offset
		var oldScrollTop = $customizer.scrollTop();
		var newScrollTop = oldScrollTop + scrollDiff;

		// Smooth scroll
		$customizer.animate({
		  scrollTop: newScrollTop
		}, 500);

	})

	$('.tms-step .tms-selection').click(function(){

		tmsSelection = $(this)

		tmsStep = tmsSelection.parent().attr('data-step')
		
		$('.tms-step[data-step=' + tmsStep + '] .tms-selection').removeClass('selected')

		if (tmsStep == 5) {
			newColor = (tmsSelection.attr('data-color') + '-bg')
			$('.wheels').fadeOut(250)
			$('.color').fadeOut(250, function(){
				$(this).removeClass(color).addClass(newColor)
				$(this).fadeIn(500)
				color = newColor
				$('.wheels').fadeIn(500)
			})
		}
		if (tmsStep == 7) {
			$('.wheels').fadeOut(250, function(){
				newWheel = ('_' + tmsSelection.attr('data-wheel'))
				oldWheel = $('.wheels').attr('class').split(' ')[1]
				$('.wheels').removeClass(oldWheel).addClass(newWheel)
				$('.wheels').fadeIn(500)
			})
		}
		if (tmsStep == 9) {
			$('.seats').css({opacity:0}).delay(500).queue(function(){
				newSeat = ('_' + tmsSelection.attr('data-seat'))
				oldSeat = $('.seats').attr('class').split(' ')[1]
				$('.seats').removeClass(oldSeat).addClass(newSeat)
				$('.seats').css({opacity:1})
				$(this).dequeue()
			})
		}
		if (tmsStep == 11) {
			$('.dash').css({opacity:0}).delay(500).queue(function(){
				newDash = ('_' + tmsSelection.attr('data-dash'))
				oldDash = $('.dash').attr('class').split(' ')[1]
				$('.dash').removeClass(oldDash).addClass(newDash)
				$('.dash').css({opacity:1})
				$(this).dequeue()
			})
		}
		/*if (tmsStep == 12) {
			$('.headliner').css({opacity:0}).delay(500).queue(function(){
				newHead = ('_' + tmsSelection.attr('data-head'))
				oldHead = $('.headliner').attr('class').split(' ')[1]
				$('.headliner').removeClass(oldHead).addClass(newHead)
				$('.headliner').css({opacity:1})
				$(this).dequeue()
			})
		}*/

		optionLeaseNew[tmsStep] = parseInt($(this).attr('data-lease'))
		optionLoanNew[tmsStep] = parseInt($(this).attr('data-loan'))
		optionCashNew[tmsStep] = parseInt($(this).attr('data-cash'))

		if (optionLeaseNew[tmsStep] > optionLeasePrev[tmsStep]) {
			leaseTotal = leaseTotal + optionLeaseNew[tmsStep]
		} 
		if (optionLeaseNew[tmsStep] < optionLeasePrev[tmsStep]) {
			leaseTotal = leaseTotal - optionLeasePrev[tmsStep]
		}

		if (optionLoanNew[tmsStep] > optionLoanPrev[tmsStep]) {
			loanTotal = loanTotal + optionLoanNew[tmsStep]
		} 
		if (optionLoanNew[tmsStep] < optionLoanPrev[tmsStep]) {
			loanTotal = loanTotal - optionLoanPrev[tmsStep]
		}

		if (optionCashNew[tmsStep] > optionCashPrev[tmsStep]) {
			cashTotal = cashTotal + optionCashNew[tmsStep]
		} 
		if (optionCashNew[tmsStep] < optionCashPrev[tmsStep]) {
			cashTotal = cashTotal - optionCashPrev[tmsStep]
		}

		optionLeasePrev[tmsStep] = optionLeaseNew[tmsStep]
		optionLoanPrev[tmsStep] = optionLoanNew[tmsStep]
		optionCashPrev[tmsStep] = optionCashNew[tmsStep]

		$('.lease-total span').text(commaNumber(leaseTotal))
		$('.loan-total span').text(commaNumber(loanTotal))
		$('.cash-total span').text(commaNumber(cashTotal))

		$(this).addClass('selected')
	
		attr = tmsSelection.parent().attr('data-next');
		if (typeof attr !== typeof undefined && attr !== false) {
			$('.tms-step[data-step=' + attr + ']').fadeIn('slow')
		} else {
			attr = $(this).attr('data-next')
			$('.tms-step[data-step=' + attr + ']').fadeIn('slow')
		}

      
		// Calculate top position of the outer node and the step we want to scroll to
		var customizerTop = $customizer.offset().top;
		var stepTop = $('.tms-step[data-step=' + attr + ']').offset().top;

		// Calculate pixel difference pixels between outer node and the next step
		var scrollDiff = stepTop - customizerTop;

		// Apply the difference to the current scroll offset
		var oldScrollTop = $customizer.scrollTop();
		var newScrollTop = oldScrollTop + scrollDiff;

		// Smooth scroll
		$customizer.animate({
		  scrollTop: newScrollTop
		}, 500);


	})

	$('.designer-thumbnail').click(function(){
		$('.close-photo-trigger').animate({opacity:1}, 250)
	})

	function commaNumber(val){
		while (/(\d+)(\d{3})/.test(val.toString())){
		val = val.toString().replace(/(\d+)(\d{3})/, '$1'+','+'$2');
	}
		return val;
	}
1 Like

Nice! Know anyone I can hire to build this out?

And you can confirm that this can be done using the CMS with custom code?

1 Like

http://experts.webflow.com :slight_smile:

Also, I don’t know if @samliew is available for hire right now, but you can ask him too. Or post on the Freelance category.

This is doable. You can even have forms with sliders like this with custom code Create and Embed a (Formula) Calculator

How are you currently structuring the up-sells/options in your CMS? What fields are you using?

Hey Sam, I’m really not able to build out the up-sells until I figure out this configuration feature.

In general, using “Text” and “Numbers” on the CMS.

This topic was automatically closed 125 days after the last reply. New replies are no longer allowed.