Streaming live at 10am (PST)

How to create nested routes on dynamic collections?


#1

I need to create a nested route for a collection to split up it’s page data.

For example, /jobs/software-engineer goes to /jobs/software-engineer/apply where “software-engineer” is dynamic to the collection.

How would I do this?


#2

Not trying to be rude (just pointing out for you), but this is currently not possible.

https://wishlist.webflow.com/ideas/WEBFLOW-I-504

https://wishlist.webflow.com/ideas/WEBFLOW-I-15

Seems like the above two can be merged into one.


#3

Yeah, seems like everything I try to do isn’t quite implemented yet… I’m slowly becoming impatient.


#4

I wish I could do something about it :cry:


#5

It’s not even for me here, it’s the fact that I feel bad for my client who isn’t getting the value they need. I really hope Webflow can step up their game and start shipping more of these features.


#6

It’s not perfect, but I was able to create a somewhat dynamic/nested page using query parameters. It just hides the elements on query parameters. Might help someone…

In this case, a job description page just listens for ?action=apply. When it pops in history, the javascript hides the description, shows a form, and scrolls to the top of the page. It’s decently robust on popstates.

Note: You could easily add other states in the switch statement, just add a new case and specify the action you want to listen for.

<script>

$(document).ready(function () {
	
  listenToHistory();
  parseActions();
	
  $('.a-button--apply').on('click', function (e) {
  	e.preventDefault();
    history.pushState({ apply: true }, 'Apply', '?action=apply');
		parseActions();
  })

})

function listenToHistory() {
	$(window).on('popstate', function (e) {
		parseActions();
  })
}

function parseActions() {
	var action = '';

	if (window.location.search && window.location.search.indexOf('action=') !== -1) {
  	var search = window.location.search;
		action = search.slice(search.indexOf('action=') + 'action='.length)
  }

  // listen for actions
	switch(action) {
  	case 'apply':
    	return (function () {
      	fadeOutSection('.job-description', function () {
        	fadeInSection('.job-application-form');
        });
      }());
    default:
    	return (function () {
      	fadeOutSection('.job-application-form', function () {
        	fadeInSection('.job-description');
        });
      }())
  }
}

function fadeInSection(className) {
  var hiddenStyles = {
  	opacity: '0',
    transition: '1s all ease-in-out'
  };
  var visibleStyles = { opacity: '1' };

	$(className)
  	.css(hiddenStyles)
  	.removeClass('is-hidden')
    .animate(visibleStyles, 200, onFinish);
}

function fadeOutSection(className, cb) {
  var hideStyles = { opacity: '0' };

	if ($(className).hasClass('is-hidden')) {
  	return cb();
  }

	$(className)
    .animate(hideStyles, 200, function () {
    	$(className).addClass('is-hidden');
      cb();
    })
}

function onFinish() {
	$('html, body').animate({scrollTop: 0}, 200);
}

</script>