On a listing or directory website, there is a list of businesses such as restaurants, coffee shops or bookstores. Each business has some information like title, introduction, review and very important – location. It’s a common demand that you want to display all the businesses on a single map, so users can view all of them at once. In this post, I’m going to show you how to do that with Meta Box.

To demonstrate the tutorial, I’m going to create a listing website for restaurants and will create a page to show all restaurants on a single map.

I’ll use a custom post type for restaurants. Each restaurant will have some information as below:

  • Title (post title)
  • Description (post content)
  • Address (a custom field)
  • Location (a custom field type Open Street Map)
  • Marker icon for the map (a URL custom field)

Maybe you want more information, but for the demonstration purpose, it’s enough.

This is the result. There are 3 listings on the map. Each listing has a custom marker icon. When clicking on the marker, a popup is displayed with restaurant title and address.

map with all listings
Display all listings on a single map with custom icons and info popup

Let’s begin!

Create a custom post type

The very first step is creating a custom post type for restaurants. You can do this with register_post_type() function. But as we’re using Meta Box, I’m going to use MB Custom Post Type extension to do this with a friendly UI.

Simply install and activate MB Custom Post Type from the Plugins → Add New screen, then go to Meta Box → Post Type and click Add New button:

create a new custom post type
Creating a custom post type with MB Custom Post Type plugin

Just add the plural, singular, and slug for the post type. You might want to set other labels or justify the settings for the post type if you want. Don’t forget to tick the checkboxes for “Title” and “Editor” in the Supports meta box on the right. We need them for the post title and post content.

Create custom fields for restaurants

To create custom fields for restaurants, I’m going to use Meta Box (of course!). If you’re new to Meta Box, then please follow the Quick Start Guide to get started.

Although I’m familiar with writing some PHP code to create custom fields, I’m going to use Meta Box Builder extension to do this job with a friendly UI. It’s a premium extension, so you need to buy it to use.

After installing and activating Meta Box Builder, you’ll see a new submenu Custom Fields under the menu Meta Box. Going there and click Add New to add a new field group. I’m going to call this group Settings, and create 3 fields:

  • Address: a text field
  • Location: an Open Street Map field
  • Icon URL: a file input field (which allows you to either enter URL in the input box or choose an image from the Media Library)

Make sure you select Restaurant in the tab Settings → Post Types.

This is what I have:

That’s all for the setup part. Now it’s time to create sample listings.

Create some listings

After having everything set up, we can create some listings for the demo. Go to Restaurants → Add New and start creating some. Don’t forget to fill in all the information in the custom fields that we created.

This is a sample listing:

creating a listing
Create a listing

Please create some listings, so we have many items to display on the map. In this tutorial, I’m going to create 3 listings.

Also, to make the listings appear beautifully, I’ll use some icons from Map Icons Collection.

all listings
All listings

Create a page template

The next step is creating a custom page template to display all restaurants on a map. You can use the archive template for this purpose if you want. But in this tutorial, for the demo purpose, I’m going to use a page template for simplicity.

So, go to your theme and add a new file called page-list.php (you can name it another way if you want). And enter the following content in the file:

<?php
/**
* Template Name: List
*/

get_header();
?>

<div id="map" style="width: 100%; height: 600px"></div>

<?php get_footer(); ?>

The page template is very simple. It loads header and footer just like other template files in your theme. In the main content area, it simply shows a div with a specific width and height. This div will be used to display the map.

Now go to Pages → Add New and create a new page. Select List from the list of available page templates:

Create a page with the new page template
Create a page with the new page template

You might wonder where is the code for the map or do we need to query all posts to get their data? That will be the next step.

Enqueue JavaScript file with location data

I’ll use JavaScript to render the map. So, the next step is enqueuing the JavaScript file. I’ll use the wp_enqueue_script function.

Enter the following code in your theme’s functions.php file:

add_action( 'wp_enqueue_scripts', function() {
    if ( is_page_template( 'page-list.php' ) ) {
        wp_enqueue_style( 'leaflet', 'https://unpkg.com/leaflet@1.5.1/dist/leaflet.css', [], '1.5.1' );
        wp_enqueue_script( 'leaflet', 'https://unpkg.com/leaflet@1.5.1/dist/leaflet.js', [], '1.5.1', true );

        wp_enqueue_script( 'list', get_parent_theme_file_uri( 'js/list.js' ), ['jquery', 'leaflet'], '1.0', true );

        $locations = [];
        $query = new WP_Query( [
            'post_type' => 'restaurant',
        ] );
        foreach ( $query->posts as $post ) {
            $location            = rwmb_get_value( 'location', '', $post->ID );
            $location['title']   = $post->post_title;
            $location['address'] = rwmb_get_value( 'address', '', $post->ID );
            $location['icon']    = rwmb_get_value( 'icon', '', $post->ID );
            $locations[]         = $location;
        }
        wp_localize_script( 'list', 'Locations', $locations );
    }
} );

What does this code do? It does the following things:

  • Enqueue Leaflet library to render maps. This is a very powerful JavaScript library that we use in Meta Box to render Open Street Maps.
  • Enqueue a custom JavaScript file to render our map. The file is put under the js folder and is named list.js.
  • Query all restaurants and get title, location, address, icon.
  • Send the restaurants’ data to JavaScript via wp_localize_script function.

Please note that I’m using rwmb_get_value here to get location data for each restaurant. This helper function returns an array of latitude and longitude, which is very useful and ready to use in the front end. See more information about this function here.

Render the map with JavaScript

The final step is rendering the Open Street Maps with JavaScript. Create a new file list.js in the folder js in your theme and enter the following code:

( function( document, Locations, L ) {
    // Set map center = first restaurant location.
    var center = L.latLng( Locations[0].latitude, Locations[0].longitude );

    // Map options.
    var options = {
        center: center,
        zoom: 13
    };

    // Initialize the map.
    var map = L.map( document.querySelector( '#map' ), options );

    // Set tile layer for Open Street Map.
    var tileLayer = L.tileLayer( 'https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png', {
            attribution: '&copy; <a href="https://www.openstreetmap.org/copyright">OpenStreetMap</a> contributors'
        } );
    map.addLayer( tileLayer );

    // Show marker for each location.
    Locations.forEach( function( location ) {
        // Marker options.
        var options = {
            title: location.title,
            icon: L.icon( {
                iconUrl: location.icon
            } )
        };
        var center = L.latLng( location.latitude, location.longitude )
        var marker = L.marker( center, options ).addTo( map );

        // Show name of the restaurant when click on the icon.
        marker.bindPopup( '<b>' + location.title + '</b><br>' + location.address ).openPopup();
    } );

} )( document, Locations, L );

The code is not very long and I already put comments there to explain each line. Let me summarize here:

  • Initialize the map. Simply following the Leaflet documentation to create a map. In this code, I set the location of the first restaurant as the initial center of the map.
  • Loop through the list of restaurants (variable Locations) and for each restaurant, create a marker for it. The code for creating markers are well documented on Leaflet docs page.
  • For each marker, bind a popup when clicking with the info of restaurant title and address.

And now, go to the front end and view the page. If nothing goes wrong, here’s what you’ll see:

View all listings on the map
Display all posts on the map

Conclusion

This tutorial helps you handling the data created with Meta Box better and outputting these data flexibly on the front end. It also helps you work with Leaflet, a very powerful JavaScript library for rendering maps (Open Street Maps). With that, I hope you can create a listing or directory website easier. If you have any comments, please share with us in the section below.

2 thoughts on “How To Display All Listings On A Map With Meta Box

  1. Perfect!
    Do you have a plan to write about creating filters for this page also? So people can sort, search by fields, categories…?

Leave a Reply