Let’s create our BuddyPress Members Map using Vue.js.

Welcome to you.

This article will explain to you how to create a fully dynamic Google Maps of your BuddyPress Members on your WordPress site, on any page.

Easily.

This tutorial is developed as we roll out this feature to our Woffice theme, intranet/extranet WordPress solution.

It already has a members map but it was:

  • 1. Not dynamic.
  • 2. Using old jQuery code.

So time for a fresh look!

To follow this tutorial you need:

  • A WordPress setup with BuddyPress installed
  • PHP skills (OOP as well) but also WordPress development skills
  • Vue.js skills (at least the basics)
  • A Google cloud account to use the Maps JavaScript V3 API (to render the map) and Map Geolocation API (to convert locations into coordinates)

We have split this tutorial into two parts: Backend & Frontend.

Makes sense right?

Nothing new here. You will see it is pretty straightforward.

Before we start, this is developed within a theme, so designed for a child theme if you do not have your own theme, but it can also be used a plugin with a couple of changes.

Also, the final (working!) result can be found as a Zipped archive at the bottom of this page.

Last but not least, lots of functions will be prefixed woffice_, change that with your own prefix.

Enough talking! Let’s get started.

Part I: Create The Backend Side

In this first part of our BuddyPress Member Map tutorial, we will create our PHP Class to handle everything in this tutorial in one single place.

Then, create the Location field to collect the member’s address. Store it safely. Once done, we will have an Ajax callback setup (which will be called by our Frontend Vue.Js component).

And we’ll optimize it to use as less requests as possible (using some home-made cache).

Getting The Member’s Location

Firstly, let’s ask a quick question: How can we collect the user’s location, easily?

No idea. Com’on…. Remember, we are teaming up with BuddyPress on this, so let’s use it! BuddyPress has a nice extension named: xProfile.

You can activate it from the Settings > BuddyPress > Components screen.

We are going to wrap all our PHP code in a class: Woffice_Members_Map, again change Woffice with your theme/plugin’s name. This class can be called from any PHP file, ideally functions.php (child or parent theme):

new Woffice_Members_Map();

We will simply create a method that will be attached to the `xprofile_updated_profile` BuddyPress action, so our code will be executed whenever someone saves its profile.

We avoid using bp_init.

Because otherwise it’s being run on every page load. However, it means you need to save your profile to generate the field. Feel free to use any other specific action, like on theme activation.

Once hooked, we run a SQL query to see if the Location field exists and otherwise we create it.

Plain and simple.

That will (should) give you a new field when you edit your BuddyPress profile. “Location”, it will hold the member’s location inside our database.

Saving The Coordinates in Our Database

We now have nice locations getting saved, but Google Map does not eat this kind of food. The diet is Geographic coordinates.

Therefore, how do we get coordinates from human-wrote locations?

Well, we use the Google API: Google Maps Geocoding API.

This API turns addresses into coordinates.

So you need to create a new Google Cloud Account (if you do not have one yet), create a new project called “Members Map” and activate this API. You can also enable the JavaScript map API as well. We will need it later on. Once both APIs created, generate API keys from the Credentials screen.

We need those.

Here is our Woffice theme’s doc article about how to get them:
Google Map Geocoding

Then, we will save all coordinates inside our database, within the wp_options table. As a new option.

Why?

Because requests are expensive to this API.

Thus, the idea is to call it only when needed, so if we already have the coordinates for one member, we don’t need it again, unless, of course, it’s being updated.

The option name in this example will be: “woffice_map_locations“. The data inside is formatted using JSON.

Let’s do it! Three new methods in our PHP Class:

  • saveSingleMember() which is hooked to the `xprofile_updated_profile` action, so whenever a new member profile is saved, we will see if there is an existing entry in our option and if not, fetch the coordinates. Same if it’s being updated.
  • getMemberCoordinates() which will fetch the Coordinates for a given member. That’s where we will call the API and the BuddyPress xProfile field.
  • apiRequest() is a helper to call the API and returns the result.

Notes:

  • We split into 3 methods because if you want to use a more complex workflow, some methods can be reused independently. Like having a button that regenerates all coordinates, we do that in Woffice and you don’t need the first method but the other two.
  • We are using a Class attribute ($privateApiKey) to hold the API key, if you have a Theme Settings page, get it from there.

Cool!

So now, we can save addresses in our profile and get coordinates saved inside our database.

That really is all we need ? Here is an example of the result in the Database:

Database preview

Creating The Ajax callback

Third step, the goal of this part is to make the coordinates we just saved inside our wp_options table available from the Frontend side, safely. Of course.

In the __construct() method, let’s add our Ajax callback functions:

If you are not comfortable with how WordPress handles Ajax requests, please have a look at this article.

Also, we are using a WordPress nonce to make the request safer and make it can only be sent through our Vue.js component.

Here is the loadMembers() method that we can add in our class:

As you can see, we are also adding a `woffice_members_map_locations` filter to let any child theme or plugin add custom data to the response using a WordPress filter.

There is also a default response if there is no coordinates found.


Part I is over! As of right now, the backend part is done. No more PHP, well, almost. Here is a quick recap of what we’ve done:

  1. Insert automatically a new BuddyPress xProfile field in the user’s profile page to collect the Location.
  2. Use the Geocoding API to turn this Location into GPS coordinates and saved them inside our database in the wp_options table as a new option to save requests.
  3. Created an Ajax callback to return the saved coordinates as a formatted array.

Real cakewalk ?

Part II: Create The Frontend Side

What we will do in this part will be to create the Vue.js component, define it, register it and call it with a PHP function.

The goal of the component is to wrap everything in a single Vue.js component (that’s the real magic!), no dependency, just this component. Once the component loaded, it will do three pretty cool, yet simple things:

  1. Create the Google Map
  2. Fetch the Members coordinates
  3. Render the Members into the map

Define Our Vue.js Component

First off, create a new file called js/wofficeMembersMap.js, it will hold our Vue.js component.

We will “enqueue” it to the page’s footer within our __contstruct() method:

And therefore, also add a new method to register both the library and our component:

As you can see, we are also embedding the Google JavaScript Map API. Therefore you need to create another (different one than the one used before the backend side: geocoding process) public key.

Once done, register it in the class as a new attribute.

Once that’s set up, you will see both JavaScript assets loaded in your source code. Now, we can create the scaffolding of our component with our newly registered “.js” file:

What are we doing here?

  • Creating a new Vue.js instance, that’s not a required step, if you’re using Vue.js already. Then just register the new component to this instance instead. Vue power!
  • Set up the markup, very easy here as it’s going to be rendered by Google Map, not us.
  • Registering our two component properties: height, url.
  • Setting up the default Vue.js hooks that we are going to use. We could use some other ones as well, for the sake of simplicity, those 2 will do just fine! Make sure to checkout this must-read doc article from Vue.js: Lifecycle diagram.
  • Note that we are using old JavaScript markup here because we (Woffice developers) want to keep support for old browsers and care a lot about the final bundle size. But this code is easily adaptable to ES6 using Babel. Nothing tricky.

Render The Component Using PHP

There are several ways to display the Vue.js component, we can use a PHP function like woffice_render_members_map() and call it from a template.

But we can also use a shortcode. Which offers the same advantages of the first method but on top of this, you can also use it right from the editor.

So, let’s create a new shortcode: [woffice_members_map] that you can use from your editor or using the do_shortcode() function from your template. The other advantage is that you can pass attributes later on if you want to extend it easily.

Nothing new here, we need to register it from our __contstruct() method.

And then, the method itself that will simply output the Vue.js component with some HTML markup.

We also pass attributes directly there to avoid using a “Data exchanger” (registering a JavaScript object in the wp_footer hook on the PHP level to pass data between PHP and JavaScript).

Create The Google Map

At the same time, we are simply going to create a new method in our component: createMap().

Which will? … … Create the map!

Not original, but makes sense.

That method will set the map’s height and use the Google Map API to generate a simple map:

Did you notice? We are using the famous component’s data object to store the map’s zoom level and center. Feel free to improve it and use shortcode/coordinates attributes. Moreover, you can use this website to get the Latitude and Coordinates of any address.

This is a VERY simple example, you can make it a LOT more complex (custom style, custom controls, animations…).

Google showcases an excellent documentation on this API. So when you use [woffice_members_map] in any post or page, you should (will, I hope) see:

Tutorial Preview

Fetch Our Members

Okay, so we have a map.

How about we now call the Ajax callback we have defined in the first step to fetch our Members coordinates from our database and render them? Sounds good.

Update the mounted() hooks to call a new method that we will define under the methods: {} object:

Couple of things to notice here:

Firstly, we are using a “WordPress nonce” to secure the request.

Secondly, we store the fetched members coordinates in the data object to be able to use it easily in any other method of our component.

Once done, we call a new method: drawMarkers().

See the next section ?

Last but not least, install the Vue.js dev tool. You will be able to visualize the data:

First Preview of our Map in Woffice

Add The Markers To The Map

Finally, here we are, the last step!

We now have a map and members coordinates, how about we do some cooking to mix them?

Sounds good to me.

Nothing fancy, let’s define the drawMarkers() method called in the last method in the fetch members’ success callback function. This method will go through all member locations we received from our backend and create a Google Map marker (more details here).

Then, we will use the user’s info, that we pass as well in the Ajax PHP callback to have some HTML markup inside the map marker. Again, easy-peasy.

As you very likely have guessed, we are using a child theme in this tutorial for our Woffice theme.

Which provides Bootstrap 4 out of the box, so no CSS, yay! I just used helper classes to get a “nice” (not bad) layout inside my marker:

Preview of WordPress BuddyPress Members Map

Which is our final result! Just this? Wait, that’s a simple example, it’s super flexible, will support as many members you want, you can change the content, style, animations, marker and a lot more.

You can see some cool examples in our Eonet and Woffice members demo pages.


In summary, what we have done in this frontend part is:

  1. Add Vue.js and the Google map public librairies to our frontend side. Plus, registering our own Vue.js component.
  2. Create a Google Map using the Google Map API v3.
  3. Fetch our members using the Ajax callback we have defined in the first step.
  4. Render the members in the map using some pretty cool map markers.

Conclusion

Hope you liked it! You are now able to create your own BuddyPress Members Map.

For any detail or improvement you have in mind, please use the comment section below.

This being said, a couple of final notes here:

  • Vue.js can be added to WordPress, VERY easily. It’s dynamic and easy to develop with. Use ES6 if you can.
  • If you have many members and they “step” on each other, consider using Marker clusters (see this article).
  • Finally, This tutorial was designed to be as simple as possible, there are dozens of improvements you can apply: using theme options, custom attributes, better marker markup, custom map style, better error handling and so on.

You can find the complete code working in a Woffice child theme in this .zip (no, I won’t collect your email address!).

Want to create your own WordPress plugin? Check out this article.

Thanks for reading and see you in the next one!

In this article, I am going to share with you guys some development practices we adopted while building our first complete Entreprise Software Web Application using Vue.js. We have been through a long nerdy journey crafting Feedier.
In a nutshell, Feedier lets you collect valuable Feedback from your customers. We challenge you to understand your customers and engage with them through our reward and engagement programs. Brand unique & enjoyable surveys. Value, engage, respect & reward your customers! ?
Enough sales talk, let’s dive right in.

Consistency matters

One of Vue.js core features are the object’s lifecycle. These give you utter control over what you want to do or set off, and when you want to.
While building our application, although we had our internal best practices, .vue files making up our app started to get longer, and we could have rapidly lost track. Developers tend to use these hooks differently, for different purposes and would lay them out differently.
For instance, some developers are keen on using the mounted hook for most of their data/API related code, while others would do that in the created hook. So you end up with inconsistency between your files.
That’s when it started to be dreadful for us.
Bottom line? Discuss and agree on how you want to structure your files and use your framework’s features beforehand.

Plan your features ahead

Is your application going to be translated? How are you going to handle the login and safety in your app? How would you design your database? These are question examples you should ask yourself before typing in any code. They are typically the kind of things we tend to implement later down the line, or tend to simply knock out, and by doing that, you increase your likeliness of breaking things. As a rule of thumb, don’t put these guys off and face them right from the inception!

And don’t trick yourself

If you get started on your first project, your team is most likely made of developers, or in other words, people eager to “build things”, and that would easily tend to forget about the main objectives: getting that application up on the market. It’s easy and attracting to implement stuff as soon as the idea comes in.
But, would your target be interested in such feature? Is it expecting it in the beta version? And are your customers willing to pay for this supposedly ‘awesome’ feature? In other word, would that be a USP?
The further you’re going away from your initial offer, the more you’re delaying your launch date.
One recommendation? Sure, get feedback, add features when everyone is convinced about their usefulness and requirement, but hold back from sinking your team in.
We’ve dragged our development phased on – and it could have been cut way off.

Get yourself up to speed with your tools

When working on a team project, because you’re using one tool doesn’t necessarily mean that you get a grasp over it. Maybe it comes from a teammates, maybe you used to be comfortable with it but haven’t used it in a while, whatever is your the reason, you need to get yourself up to speed!
Most of today’s modern tools are getting updated so often that we tend to miss important and stunning new features.
The point is, read the doc again, be confortable, it will save you time on the long run. Instead of rustling up a workaround, or looking for a solution in the doc, you will be confident from the beginning on.
Just to give you an example, at the beginning of our Feedier journey, we almost missed the Events Bus at the outset, so we were kinda coming up with our solution. And then we found out about that, so we changed everything. Worth doing it, but still, it could have saved us some hassles to do it from scratch.

Forget about console.log

Just shedding some lights into the available alternatives and why you would ditch your favorite console.log trick.
Again, Vue offers its stunning development tool – Vue.js devtools – available on Chrome and Firefox. This plugin gives you extreme flexibility and definitely cut the development time back! Among other, it gives you the ability to tweak data value, navigate straight to the Vue.js component from the DOM inspector, flick through the different Events, and, first and foremost, gives you the data and computed properties values.
For instance, while building our onboarding widgets, instead of fiddling with our API to mock some data and make sure the onboarded attribute was always false, we simply had to change its value in the browser. Easy peasy!
Toggling a boolean or change a data relying on a bunch of conditions, events and some API calls becomes a no-brainer.

Vue.js dev tool
Vue.js dev tool

Besides this, Webpack is also great when it comes to debugging. By simply using the eval-source-map property in your dev config, you get all of your .vue components available in the Browser and the right line mentioned when there is an error cropping up. One click, and you jump to the line, even though everything is bundled and compiled under the hood. Gorgeous, isn’t it?
Suffice it to say, you have everything you need for a decent working environment. You “just” have to build.

Plan and lay out your code architecture

As most modern JS frameworks, Vue.js gives you have the ability to split your code into reusable components. This is brilliant, and that’s why before writing any code, you have to ask yourself:

  • Is there any piece of my code that could be used anywhere else with other data?
  • If so, how can I make it flexible, open to modification, extensive and reusable with ease?

Feedier dashboard preview
Feedier dashboard preview – could you guess how many components do we have on this page?

Finding the right trade-off between too much props and not enough components is tough though. As a rule of thumb, avoid overrunning your components with props anyway!
But that’s not all, you must also watch out for long clunky files that would make your experience as a developer worse and worse overtime. It was especially true with our JS helpers file. Every helper was just adding up, but the file became unusable. We had to break that up into a bunch of meaningful files, reaping the benefits of ES6 import/export features.
Doing that from the outset would have saved us time, efforts and bugs.

Hold back from using third-party packages when possible

Make no mistake, Open Source is fantastic ! Building a complete web applications takes a sh*tload of time and resources, that’s why it’s very tempting to rely on a NPM package to do your job whenever there is one available.
It’s also really enticing to install the latest package that got very popular on Github last week, or was mentioned in a bunch of articles on Medium and seems useful for your project.
But …. you actually have to factor in the real benefits of using it over building a simple handmade script that would do the job just fine! Our motto would be: draw it up yourself whenever you can! And only fall to the package back if it substantially reduce the amount of work, or you have no way but to do it.

Sample of or core packages
Sample of our core packages

Restricting yourself to the foremost plugins also reduce your overall script size and contribute to your web-app speed. That said, picking the right tools and avoid swamping yourself with the tons of packages isn’t a breeze!
By the way, if you’re wondering what is Apollo and GraphQL about, check out this article, we explain the nitty-gritty details about GraphQL and why it matters. It’s definitely worth reading. Long story short? If you’re still wondering how on earth you’re going to structure your Rest API – stop thinking, and jump straight into a GraphQL server, which is nicely integrated with the Apollo client thanks to this vue-apollo plugin.
To conclude, if you have a great business idea for your next application, don’t shy away – and move forward! Validate your idea rallying your friends’ feedback, and creating your Business Model Canvas. Then, get your MVP out, with the most important features, and collect feedback from that. You just want your users to get to that AHA moment as soon as possible. You have all the tech advices you need, let’s go!
We hope this article has been helpful and will help anyone embracing the gorgeous Vue.js for his next venture!
Any question, feedback or idea? Just throw a comment away below. ?
By the way, we are currently in beta mode, join our crew and make your customers feel valued now at feedier.com