Streaming live at 10am (PST)

Dynamic Forms with Webflow CMS


#1

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


#2

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

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


#4

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;
	}

#5

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?


#6

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.


#7

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?


#8

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.


#9

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