0

I have set up a custom post type and taxonomy. The post type is called Local Services and the hierarchical taxonomy is called Regions. The Regions have child categories called Areas. I have set up a custom page to display my results. So far I have managed to display the latest 10 posts. But what I NEED to do is display one result on this page. To do this I need to have a drop down menu of regions and then according to which region is picked, this would then display a second drop down menu of the child areas. The user would then select one area.

I would like to display the result on my custom template page so when a visitor goes to the page initially, there would be a brief intro description with the drop down menu of Regions.

This sounds relatively simple and I looked at similar questions here but can't find a solution.

Can anyone help please?


This is what I have so far in my custom page template which displays a single result (the most recent). But I would like my page to display a drop down list of regions and another with their associated areas so a user will then get a single result displaying their chosen area. The page should not display any custom post information until a user has made these 2 choices.

$args = array( 
    'post_type' => 'local_services', 
    'posts_per_page' => 1 
); 
$loop = new WP_Query( $args ); 
while ( $loop->have_posts() ) : $loop->the_post(); 
    the_title(); 
    echo '<div class="entry-content">'; 
        the_content(); 
    echo '</div>'; 
endwhile;

UPDATE: 12 DECEMBER

My custom post and taxonomy code:

<?php 
function create_post_type() {  
    register_post_type( 'local_services',  
        array(  
            'labels' => array(  
                'name' => __( 'Local Services' ),  
                'singular_name' => __( 'Local Service' ), 
                'edit_item' => __( 'Edit Local Service' ),
            'update_item' => __( 'Update Local Service' ), 
            ),  
        'public' => true,  
        'menu_position' => 5,  
        'rewrite' => array('slug' => 'local-services')  
        )  
    );  
}  

add_action( 'init', 'create_post_type' );  
function region_taxonomy() {  
   register_taxonomy(  
    'region',  
    'local_services',  
    array(  
        'hierarchical' => true, 
        'label' => 'Region',  
        'query_var' => true,  
        'rewrite' => array('slug' => 'region')  
    )
);  
}  
 add_action( 'init', 'region_taxonomy' );  
?>

UPDATE: 18 DECEMBER

I looked at the wp_dropdown_categories and found some code to customise it. I decided to go for a simpler option of just one dropdown instead of two. I created a new custom post type "services" and a new taxonomy "area".

I put the new code in my sidebar:

   <?php
    $categories = get_categories('taxonomy=area');
    $select = "<select name='cat' id='cat' class='postform'>n";
  $select.= "<option value='-1'>Select your local area</option>n";
    foreach($categories as $category){
    if($category->count > 0){
        $select.= "<option value='".$category->slug."'>".$category->name."</option>";
    }
  }
   $select.= "</select>";
    echo $select;
   ?>

<script type="text/javascript"><!--
    var dropdown = document.getElementById("cat");
    function onCatChange() {
        if ( dropdown.options[dropdown.selectedIndex].value != -1 ) {
            location.href = "<?php echo home_url();?>/services/"+dropdown.options[dropdown.selectedIndex].value+"/";
        }
    }
    dropdown.onchange = onCatChange;
--></script>

I also created a custom template "single-services.php" to display the result content. As I only want a single result per query this works great.

5
  • 3
    Have you done some work yourself to achieve this? If so share the code you tried and explain what is and isn't working. Dec 5, 2013 at 16:26
  • Yes, I have got some basic code in my local services page template. I have set it to return one post but it is the most recent post so not what I am trying to do. Here's the code: <?php $args = array( 'post_type' => 'local_services', 'posts_per_page' => 1 ); $loop = new WP_Query( $args ); while ( $loop->have_posts() ) : $loop->the_post(); the_title(); echo '<div class="entry-content">'; the_content(); echo '</div>'; endwhile; ?>
    – Jean
    Dec 8, 2013 at 19:43
  • Please add code to the question, because it's not nicely readable in comments. Dec 8, 2013 at 21:53
  • ok, thanks, am new to this site so will do so in future.
    – Jean
    Dec 9, 2013 at 11:52
  • Not a problem, I've no time for an answer right now, but take a look this answer I gave a couple of days ago to get you started. It is possible to do this with two dropdowns. Dec 9, 2013 at 11:58

2 Answers 2

2

Like I said in the comment, this can be solved by using two dropdowns. Additionally I already hinted you to an answer of mine doing this for a simple, one level, non conditional category selection. Category dropdowns can easily constructed with wordpress by making use of wp_dropdown_categories.

To make it work as actual selection handed over to a query the dropdown has to be part of a form. This way the variable constructed according to the form method can be used for the query to be performed. I've chosen POST as method here, GET would be the other possibility, take a look at my linked answer for a little bit more information on that. The method how the form is constructed is an adaptation of this example from the wp_dropdown_categories() codex page. Key here is to disable echoing and to adapt the select output. By doing it this way we can have a button less form submit, but, if no javascript is available, we have a fallback to show the button - the button is wrapped into noscript tags.

For this setup several steps are necessary. The solution below operates with a hierarchical taxonomy to distinguish between regions and areas - in case of a custom taxonomy you have to make use of the taxonomy parameter. In a first step, we wanted to make sure that the regions dropdown only shows the top level in the hierarchy, this is done with the parameter hierarchical and depth. Additionally there are conditional states for the cases »no option selected« and »option has been selected« - parameters show_option_none and selected, dependent on $_POST['region'].

The second, area dropdown gets only shown if a region was selected before. It wouldn't be useful otherwise anyways, because its content is determined by the first, region dropdown. For this the child_of parameter is brought to use, of course bringing this back to the selected region saved in $_POST['region']. Another thing to do is making sure we keep the information about the region, for this the hidden input is part of the second form. The latter assures that we loop through the region as long as we're just changing the areas.

The last part of the setup takes care of conditionally giving back the content. for one we want to make sure to show a post only if a region and area is selected. If that's the case the correct post is determined by making use of the cat parameter of WP_Query. Like shown below it's possible to use the conditions to show additional information for the user.

Code:

Part 1:

    <form method="POST" action="">
        <div>
            <?php
                $args = array(
                    // hierarchical is needed to define depth
                    'hierarchical' => 1,
                    // regions are the top level in a hierarchical taxonomy
                    'depth' => 1,
                    'orderby' => 'name',
                    // we're not echoing, because we want to construct a no button solution
                    'echo' => 0,
                    'taxonomy' => 'regions',
                    // this leads to variable name $_POST['region']
                    'name' => 'region'
                );
                if( ! isset($_POST['region']) ):
                    // if no region was selected prior we show this by default
                    $args['show_option_none'] = 'Select Region';
                else:
                    // otherwise make sure the region form shows what was selected before
                    $args['selected'] = $_POST['region'];
                endif;
                // we're putting the dropdown output into a variable
                $region = wp_dropdown_categories( $args );
                // this enables the buttonless js possibility
                $region = preg_replace("#<select([^>]*)>#", "<select$1 onchange='return this.form.submit()'>", $region);
                // now echo the dropdown output
                echo $region;
                // the »<noscript>...</noscript> part makes sure there is a fallback in case there is no js
            ?>
            <noscript>
                <div>
                    <input type="submit" value="region" />
                </div>
            </noscript>
        </div>
    </form>

Part 2:

    <?php
        // the area dropdown is only shown if a region was selected
        if( isset($_POST['region']) && $_POST['region'] ):
    ?>
        <form method="POST" action="">
            <?php // we add a hidden input to hand over the region selected ?>
            <input type="hidden" name="region" value="<?php echo $_POST['region'] ?>">
            <div>
                <?php
                    $args = array(
                        // the areas to show are children of the prior selected region
                        'child_of' => $_POST['region'],
                        'hide_if_empty' => true,
                        'orderby' => 'name',
                        'echo' => 0,
                        'taxonomy' => 'regions',
                        'name' => 'area'
                    );
                    if( ! isset($_POST['area']) ):
                        $args['show_option_none'] = 'Select Area';
                    endif;
                    $area = wp_dropdown_categories( $args );
                    $area = preg_replace("#<select([^>]*)>#", "<select$1 onchange='return this.form.submit()'>", $area);
                    echo $area;
                ?>
                <noscript>
                    <div>
                        <input type="submit" value="area" />
                    </div>
                </noscript>
            </div>
        </form>
    <?php endif; ?>

Part 3:

    <?php
        // we're only performing a query if both a region and an area have been selected
        if( isset($_POST['region']) && isset($_POST['area']) && $_POST['region'] && $_POST['area'] ):
            $args = array( 
                'post_type' => 'local_services',
                // this assures the post is selected by the area selected
                'cat' => $_POST['area'],
                'posts_per_page' => 1 
            ); 
            $loop = new WP_Query( $args ); 
            while ( $loop->have_posts() ) : $loop->the_post(); 
                the_title();
                echo '<div class="entry-content">'; 
                    the_content(); 
                echo '</div>'; 
            endwhile;
        // show conditional information according to the step we're at
        elseif( isset($_POST['region']) && ! isset($_POST['area']) && $_POST['region'] ):
            echo 'Please select an area';
        else:
            echo 'Please select a region';
        endif;
    ?>

I only divided this into parts to make it a little bit better readable, those three parts actually are seamlessly together. This can be used directly in your according template, or a function could be constructed of this, if you want to keep your templates clean. That's about it. As you have seen, I commented the code too, so, with above explanation, the procedure should be pretty clear. Take a look at the according documentations or do a search on here to further customize it to your needs.


Note: I've tested this and running similar to this, so I'm not sure what the problem the OP has been experiencing was. As far as I'm concerned, this is working.


Edit: in response to comment

Are you debugging? You might have conflicting query vars here, because your taxonomy name is actually »region« not »regions«. Instead of using

'query_var' => true

you could try

'query_var' => 'regions'

Or you give the form another name then region, do not forget to change all the related $_POST variables accordingly.

8
  • Thank you so much ialocin. I will take a good look at this tomorrow and work through it.
    – Jean
    Dec 10, 2013 at 16:14
  • My pleasure, I've a open heart for charity :) I've tested this, or to be exact have it running like this, so you normally should just have to make sure you implement and configure it to your needs. @Jean Dec 10, 2013 at 16:18
  • I have put the code in my custom template. The dropdowns work fine but I cannot display any results on my page. I have read the codex about wp_dropdown_categories but cannot find an answer. This is the first time I have used custom post types so I may have made an error in my code (above). I originally stated that my taxonomy was called "regions" but in fact it is "region". I have changed the two references to "regions" in the conditional dropdown code so it all matches up. Any ideas why it's not displaying any results? Thank you for any help.
    – Jean
    Dec 12, 2013 at 20:53
  • Sadly not as yet.
    – Jean
    Dec 16, 2013 at 15:12
  • Too bad, have you debugged it? And checked the variables - print_r($_POST) - and the query object - print_r($loop). I'm certain there must be a configuration problem, because the general concept proposed is working for sure. @Jean Dec 16, 2013 at 15:36
0

The Code from ialocin works pretty well, but if you want to use a custom taxonomy, then it is supposed to be like this:

Part 1:

 <form method="POST" action="">
    <div>
        <?php
            $args = array(
                // hierarchical is needed to define depth
                'hierarchical' => 1,
                // regions are the top level in a hierarchical taxonomy
                'depth' => 1,
                'orderby' => 'name',
                // we're not echoing, because we want to construct a no button solution
                'echo' => 0,
                'taxonomy' => 'regions',
                // this leads to variable name $_POST['region']
                'name' => 'region'
            );
            if( ! isset($_POST['region']) ):
                // if no region was selected prior we show this by default
                $args['show_option_none'] = 'Select Region';
            else:
                // otherwise make sure the region form shows what was selected before
                $args['selected'] = $_POST['region'];
            endif;
            // we're putting the dropdown output into a variable
            $region = wp_dropdown_categories( $args );
            // this enables the buttonless js possibility
            $region = preg_replace("#<select([^>]*)>#", "<select$1 onchange='return this.form.submit()'>", $region);
            // now echo the dropdown output
            echo $region;
            // the »<noscript>...</noscript> part makes sure there is a fallback in case there is no js
        ?>
        <noscript>
            <div>
                <input type="submit" value="region" />
            </div>
        </noscript>
    </div>
</form>

Part 2:

    <?php
    // the area dropdown is only shown if a region was selected
    if( isset($_POST['region']) && $_POST['region'] ):
?>
    <form method="POST" action="">
        <?php // we add a hidden input to hand over the region selected ?>
        <input type="hidden" name="region" value="<?php echo $_POST['region'] ?>">
        <div>
            <?php
                $args = array(
                    // the areas to show are children of the prior selected region
                    'child_of' => $_POST['region'],
                    'hide_if_empty' => true,
                    'orderby' => 'name',
                    'echo' => 0,
                    'taxonomy' => 'regions',
                    'name' => 'area'
                );
                if( ! isset($_POST['area']) ):
                    $args['show_option_none'] = 'Select Area';
                endif;
                $area = wp_dropdown_categories( $args );
                $area = preg_replace("#<select([^>]*)>#", "<select$1 onchange='return this.form.submit()'>", $area);
                echo $area;
            ?>
            <noscript>
                <div>
                    <input type="submit" value="area" />
                </div>
            </noscript>
        </div>
    </form>
<?php endif; ?>

Part 3 (changes are made here):

 <?php
    // we're only performing a query if both a region and an area have been selected
    if( isset($_POST['region']) && isset($_POST['area']) && $_POST['region'] && $_POST['area'] ):
        $args = array( 
            'post_type' => 'local_services',
            // this assures the post is selected by the area selected
            // usage of custom taxononmy
            'tax_query' => array (
                array (
                    'taxonomy' => 'bundesland',
                    'field' => 'term_id',
                    'terms' => array($_POST['area']),
                ),
            ),
            'posts_per_page' => 1 
        ); 
        $loop = new WP_Query( $args ); 
        while ( $loop->have_posts() ) : $loop->the_post(); 
            the_title();
            echo '<div class="entry-content">'; 
                the_content(); 
            echo '</div>'; 
        endwhile;
    // show conditional information according to the step we're at
    elseif( isset($_POST['region']) && ! isset($_POST['area']) && $_POST['region'] ):
        echo 'Please select an area';
    else:
        echo 'Please select a region';
    endif;
?>
0

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.