Skip Navigation

[Resolved] CRED show group conditional for parent post type

This support ticket is created 7 years, 11 months ago. There's a good chance that you are reading advice that it now obsolete.

This is the technical support forum for Toolset - a suite of plugins for developing WordPress sites without writing PHP.

Everyone can read this forum, but only Toolset clients can post in it. Toolset support works 6 days per week, 19 hours per day.

No supporters are available to work today on Toolset forum. Feel free to create tickets and we will handle it as soon as we are online. Thank you for your understanding.

Sun Mon Tue Wed Thu Fri Sat
- 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 7:00 – 14:00 -
- 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 15:00 – 16:00 -

Supporter timezone: Europe/London (GMT+01:00)

This topic contains 10 replies, has 2 voices.

Last updated by Nigel 7 years, 10 months ago.

Assisted by: Nigel.

Author
Posts
#402946

I am trying to: set up a conditional parent element in a CRED form like so:

[cred_field field='_wpcf_belongs_state_id' value='' order='date' ordering='desc' required='true' select_text='--- Select state ---' validate_text='state must be selected']
[cred_show_group if="($(state) eq  'Western Australia' )"  mode='fade-slide']
    Select WA Region // do more stuff
[/cred_show_group]

I can make this work if I use a simple select element but of course this doesn't assign it to the parent.

I visited this URL: https://toolset.com/forums/topic/conditional-if-a-parent-post-exists-and-its-custom-field-is-not-empty-then/

Which suggests that it is possible to test for _wpcf_belongs fields in a view

I expected to see: this is possible within a cred form too

Instead, I got: well, it didn't work.

#402990

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+01:00)

You can show a group of form elements conditionally based upon the value of another field in the form, as described here: https://toolset.com/documentation/user-guides/conditional-display-for-form-inputs/

What exactly is it you are trying to do?

You have a State CPT which has a child CPT Region, and you have presumably already published your states and corresponding regions.

What is your CRED form creating? A different CPT? And you want to select a State for this other custom post, and then conditionally reveal the regions for that state so that one can also be selected? And you will be storing these as custom fields?

This sounds like a job for a custom taxonomy, but in any case if you could clarify what you aim to achieve then I can help you get it working.

#403000

Hi Nigel,

Thanks for the reply.

I am trying to have a two step process where people select their region. First they select their state ( which is a parent CPT ) and then based on what state they select I display another option to select their region ( child of state ).

States have been set up with corresponding regions.

CRED form is creating another CPT called Listings ( business listings in a directory ) which is a child of Region.

Custom Taxonomy was my first approach but this won't allow me to set up the two step state/region parameter in the parametric search view as seen in the Real Estate demo.

#403132

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+01:00)

Hi James

I just wanted to let you know that I'm still working on it.

It is actually quite a thorny issue that can't simply be done out-of-the-box with Toolset in the way you describe and I am still thinking through the problem and will let you know as soon as I can what my conclusions and recommendations are.

Thanks for you patience.

#403440

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+01:00)

WJq1Yojk91.gif

Hi James

So, first the good news. If you look at the attachment you will see something along the lines of what you are looking for. Select your state and the available regions narrows-down accordingly.

This is definitely the kind of thing that taxonomies should be used for, but as you have already discovered, you cannot set up the parametric searches the way you want using a hierarchical taxonomy. I have put in a feature request for this, but am told it is in the pipeline but not currently being worked on.

Which means employing the same workaround as used in the real estate demo site you referenced, using custom post types in place of the taxonomy. You can use the real estate reference site to see how the parametric search works, but, unfortunately, it is not any help in adding something similar to your CRED forms for when the listings are published.

A solution using custom code is required, and ordinarily I would say that such code is beyond the support we can offer, but as this relates to a shortcoming in Toolset and you have been encouraged to go down the route suggested by the real estate demo, I have worked out a bare bones solution which I hope you will be able to adapt to your needs.

So, you have a hierarchy of CPTs like so: state > region > listing.

And to restate what you want to achieve, in your CRED form to create listings you want to be able to first select your state, then select the corresponding region from those that belong to the chosen state.

The problem with the solution you posed in your question is that there is no direct connection between listings and states. As a child post of a region, your listing will have the hidden meta field '_wpcf_belongs_region_id' which stores the id of the parent region.

But it doesn't have an equivalent for the state, because a listing is not a child of a state, and on your listing CRED form there is no way to reference the grandparent state.

(Making listings children of states as well might help but I wasn't sure how that might interfere with your parametric search.)

In any case, your solution of using conditionals based upon the state (even if we knew it) to show or hide a series of region select boxes populated with only the regions for that state doesn't work because there is no way to tell Toolset to generate the HTML for the select box for only a subset of the possible values.

So, my solution works along the following lines.

First, I need a select box for the states on my CRED form, even though we don't need to store the state, we will just be using it to update the region select box. You could use Views and Types shortcodes to construct it, but I used Types to set up a custom field for states and added that to my form. Note, all the code will work with the post_id's of the states and regions, so your option values will need to be the id's of your states.

So, from my state select box I will know the state id, but how will I know what regions are its children?

The only way I could get this to work was to build an object which mapped the relationship between states and regions with some custom PHP, and then use the WordPress function wp_localize_script to make that object available to JavaScript on the front end.

With that, it is relatively straightforward to respond to changes to the state select box and update the options available in the regions select box accordingly.

First my custom PHP which I have added to my theme's functions.php file:

/**
 * Pass a 'locations' object to the front end
 */
function pass_state_region_object() {
	// Get all the states
	$states = get_posts( array('post_type' => 'state', 'post_per_page' => -1 ) );

	$locations = array();

	foreach ($states as $state) {
		// get the regions which this state is parent of
		$args = array(
			'post_type'			=> 'region',
			'posts_per_page'	=> -1,
			'meta_query'		=> array(
				array(
						'key'	=> '_wpcf_belongs_state_id',
						'value'	=> $state->ID
					)
				)
		);
		$regions = get_posts( $args );

		$region_ids = array();
		foreach ($regions as $region) {
			$region_ids[] = (string)$region->ID;
		}
		$locations[$state->ID] = $region_ids;
	}

	// Register front-end script
	wp_register_script( 'custom', get_template_directory_uri() . '/js/custom.js', array( 'jquery' ) );

	// Pass the data via localize script
	wp_localize_script( 'custom', 'locations', $locations );

	// Enqueued script with localized data.
	wp_enqueue_script( 'custom' );
};
add_action( 'wp_enqueue_scripts', 'pass_state_region_object' );

Note here that I am passing the object locations to my script "custom.js" which I have enqueued. Your folder locations etc. may vary, I am working in the default twentysixteen theme.

Here is my custom.js file:

( function( $ ) {
	$( document ).ready( function() {

		// add event listener so we react to changes in the State select box
		$("[name='wpcf-state']").change( function(e){
			// pass on the selected State to the function which will update Region select box
			var state = $("[name='wpcf-state']").val();
			updateRegion(state);
		});

		function updateRegion(state){
			$("[name=_wpcf_belongs_region_id] > option").each( function(){
				var match = false;
				if ( this.value !== "-1" ) { // leave nothing-selected intact

					for (var i = 0; i < locations[state].length; i++) {
						// check if this region belongs to the parent state
						if ( this.value === locations[state][i] ) {
							match = true;
							break;
						}
					}
				} else {
					match = true;
				}
				if (!match) {
					$(this).remove();
				}
			});
		}
	} );
} )( jQuery );

That should work.

But. It is a fairly crude solution to get you started. There are a couple of things that want fixing, which I'll leave as homework for you, but if you are struggling then let me know.

The first is that my PHP code runs on every page, you would want to add a test for the page where your CRED form is.

The second is that the JavaScript solution is destructive: select a state and it removes all the regions for the other states. Change the state again and you will be left with nothing. You should make a clone of the complete regions select box which you can use to start over from the full list of regions when changing the state select box.

#403991

Hi Nigel,

I am just taking a minute here to thank you for such a thorough answer to this problem.

I will start looking at it now and get back to you over the next couple of days with how I get on.

I am grateful for the homework too because this is a great learning exercise for me. I hadn't seen much of wp_localize_script before and didn't actually understand what it does - the name isn't as obvious as enqueue_script for example and I am sure I had wondered before about how to pass info from php to js.

Thanks again mate and I'll get back to you on how I go shortly.
Chris.

#403997

Hi Nigel,

So one initial problem that I don't understand and a question too.

The problem is that this line:

for (var i = 0; i < locations[state].length; i++) {

is throwing an error because locations is undefined.

The question is about making the regions select into a muti-select box. I have tried this before but it doesn't always seem to work - is there anything that would prevent it from working like this?

Thanks mate,
Chris.

#404028

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+01:00)

Hi James

If you are getting an error because locations doesn't exist then something has gone wrong using wp_localize_script to pass the object from PHP to your JS file.

Double-check by trying to console.log(locations) on the first line of your JS file.

wp_localize_script can be used to pass a variable to a named script on the front end. You don't have to make and enqueue a new JS file specifically for this, but you must be careful that the JS file is enqueued properly and that you use the same handle when enqueuing and localizing the script.

Here's the official documentation for wp_localize_script: https://codex.wordpress.org/Function_Reference/wp_localize_script, and a simple tutorial which is where I first discovered it: hidden link

When locations is available in your script the above code should work (sorry, it hasn't formatted as a code block for some reason).

Regarding using a multi-select box for regions, I'm not sure what "doesn't always work" means, but it should work in principle. Let me know if you experience a specific problem.

#404307
Screen Shot 2016-06-04 at 7.34.25 AM.png

Hi Nigel,

So Locations was getting passed fine it was the State that wasn't working properly because the Select element in the post fields wasn't tied to to the parent State.

I just needed to set Custom field content for each option to the post ID and it works fine. Pretty excited about that, thanks!

What "doesn't always work" means is that I haven't figured out how to make it work properly. I have attached a screenshot with three selects. The two on the left are the newly working state/region selects and the one on the right is from a Services taxonomy.

How can I make the Select Regions select element display as a multiple select? I can do it with jQuery but is there a way to do it in the cred form itself?

Thanks again for all you help.
Chris

#404322

An FYI for anyone else trying to follow this thread:

One point to mention is that I discovered that only the five most recently published 'states' were getting their regions added to the 'locations' variable before it go passed.

I had to change the first line of the function pass_state_region_object to include the numberposts parameter because WP has a default value of five for this:

// Get all the states
$states = get_posts( array('post_type' => 'state', 'post_per_page' => -1, 'numberposts'=> -1 ) );
#404620

Nigel
Supporter

Languages: English (English ) Spanish (Español )

Timezone: Europe/London (GMT+01:00)

CRED forms don't have the option to output multi-select boxes for Types fields (although they can be used for generic fields).

I'm not sure you would want to display a multiselect box for you regions in the first instance, anyway, as until you select the State the entire list of regions would be shown. The default rendering of multiselect boxes in most browsers isn't ideal, and if your theme is not already doing so, I suspect you would want to customise the multiselect box rendering via a library to something more like this anyway: hidden link

But, there is a bigger issue here. Parent > Child post type relationships are one-to-many. Parents can have many children, but children cannot have many parents OF THE SAME TYPE.

You can set up post relationships so that child post types can have multiple parent post types. If your Listings are supposed to be available in different Regions then you may need to think about restructuring things so that Regions are child post types of both States and Listings.

This ticket is now closed. If you're a WPML client and need related help, please open a new support ticket.