[Vue.js] Using the KAKAO Postal Code Address API

[Vue.js] Using the KAKAO Postal Code Address API

Use the postal code API provided by Kakao in the vue.js project.

1. Set up the project

omit

2. Test the library

Refer to the postcode (and address search) API page provided by Kakao and write the related module.

2.1. Import the library

To use the API, you need to import the js file below.

JAVASCRIPT
https://t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js

there are two ways to import libraries.

  1. import with a <script> tag in your HTML file
  2. dynamically generate <script> tags to import JS files

in this example, we'll import the JavaScript for the Postcode API into an html file for ease of implementation.

if you created a vue project using the vue cli, the html for the template exists by default under the public directory.

TXT
[PROJECT ROOT] +- public +- index.html (!) +- src +- App.vue +- main.js

open the index.html file and import the js file provided by the document inside head.

HTML
<!DOCTYPE html> <html lang=""><! <head> <! ... <script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script> </head> <body> ... </body> </html>

when imported as above, the library installs the required library code into the window built-in object.

TXT
window.daum.Postcode

2.2. Test

to check how to use it, open the address search bar in a new window.

create the top-level component file PostCodeApp.vue for the test.

TXT
[PROJECT ROOT] +- public +- index.html +- src +- App.vue +- PostCodeApp.vue (+) +- main.js

replace the top-level component in main.js with PostCodeApp.vue.

JAVASCRIPT
import Vue from "vue"; // import App from './App.vue' (-) import PostCodeApp from "./PostCodeApp.vue"; (+) Vue.config.productionTip = false; new Vue({ // render: (h) => h(App), // (-) render: (h) => h(PostCodeApp), // (+) }).$mount("#app");

fill in the contents of the PostCodeApp.vue file as shown below.

PostCodeApp.vue
<template> <div class="postcode-demo <div class="postcode-demo"> <button @click="showPopup()">Test button</button> </div> </template> <script> </script export default { data() { return { }; }, mounted() {}, methods: { showPopup() { alert('Open the address search bar here') } }, }; </script> <style></style>
  • if you type the string vue in the newly created vue file and press tab, the default template is automatically generated.

verify that the test button comes out correctly on the browser screen. an alert window should pop up when the button is pressed.

now, write the code below to display the address search box when the button is pressed.

PostCodeApp.vue
export default { data() { return { }; }, mounted() {}, methods: { showPopup() { // alert('Open address search box here') new window.daum.Postcode({ oncomplete: function(data) { // This is the part where we write the code that will be executed when the search result item is clicked in the popup. // Check out the example to see how it can be utilized. } }).open(); } }, };
  • new window.daum.Postcode({..}) - creates an instance of the address bar
  • .open() - opens the address bar as a popup window

go back to the browser and press the button to open the popup window.

oncomplete callback

when you search for an address in the address search box and click on any address in the list that is displayed, you can get the information of the clicked address through the oncomplete callback.

PostCodeApp.vue
export default { ... methods: { showPopup() { ... new window.daum.Postcode({ oncomplete: function(data) { console.log(data) // console output } }).open(); } }, };
  • method argument data is the clicked address information.

the important fields of the address information are as follows

JAVASCRIPT
{ .., jibunAddress: "275-2, Macheon-dong, Songpa-gu, Seoul, Korea", jibunAddressEnglish: "275-2, Macheon-dong, Songpa-gu, Seoul, Korea", .., roadAddress: "6-3, Gaminam-ro, Songpa-gu, Seoul, Korea", roadAddressEnglish: "6-3, Gaminam-ro, Songpa-gu, Seoul, Korea", .., zonecode: "05762" }
  • jibunAddress - existing address (with English)
  • roadAddress - street address (with English)

use the address information passed to the oncomplete method to populate the necessary forms in the context of your application.

3. Build the component

in mobile environments, it is often inappropriate to display a popup window. The Kakao Postcode Search API provides the ability to embed the address bar in a specific element.

3.1. embedding mode

in this case, we will create the address search box as a separate component and embed it wherever we need it.

create a file called PostCode.vue under the components directory like this The address bar that pops up will be located in this file.

TXT
[PROJECT ROOT] +- public +- index.html +- src +- components +- PostCode.vue (+) +- App.vue +- PostCodeApp.vue +- main.js

create a PostCode.vue file like the one below.

PostCode.vue
<template> <div class="postcode-wrapper <div class="postcode-wrapper"> <div class="body" ref="postarea <div class="body" ref="postarea"> <!-- Here is the address bar <!-- We want to put the address bar here --> </div> </div> </template> <script> <! export default { mounted() { console.log("[SHOULD NOT NULL]", this.$refs.postarea); new window.daum.Postcode({ oncomplete: (data) => { console.log("[Selected address]", data); }, }).embed(this.$refs.postarea); }, }; </script> <style></style>

the postcode (address) search API requires you to specify a dom element to embed the address search bar.

in a VUE-based project, you can use REF to access a specific DOM element.

in the code above, we've defined the ref attribute value postarea on an element with class value ".body" (the name of the attribute value is arbitrary for context)

and in the javascript area, we can get a reference to the dom element, like this.$refs.postarea.

finally, if you call embed(..) immediately after creating the address bar instance, the address bar will be created inside ".body".

3.2. Using Components

in PostCodeApp.vue, we use the PostCode.vue component.

PostCodeApp.vue
<template> <div class="postcode-demo <div class="postcode-demo"> <button @click="showPopup()">Test button</button> <PostCode /> <!-- (3) Enable --> </div> </template> <script> import PostCode from './components/PostCode.vue' // (1) import component export default { components: { PostCode, // (2) register as a local component }, data() { return { }; }, methods: { showPopup() { alert('Open address search bar here') } }, }; </script> <style></style>

to add a component, you need to do three things

  1. import the component you want to use
  2. register it as a local component
  3. use it inside <template>...</template>

for now, PostCode.vue will appear right on the screen.

3.3. Conditional Rendering (v-if)

i want a popup to appear only when a button is pressed.

to do this, define the visible variable in PostCodeApp.vue as shown below.

PostCodeApp.vue
<template> <div class="postcode-demo <div class="postcode-demo"> <button @click="showPopup() <button @click="showPopup()">Test button</button> <PostCode v-if="visible"/> <!-- (2) Only when visible is true --> </div> </template> <script> import PostCode from "./components/PostCode.vue"; export default { components: { PostCode, }, data() { return { visible: false // (+) false, start PostCode invisible }; }, methods: { showPopup() { // Changing visible to true will render the PostCode component this.visible = true } }, }; </script>
  • calling the showPopup() method when the button is clicked
  • in showPopup(), we change the visible variable to true
  • component PostCode rendered on screen only when visible variable is true

3.4. Passing the address $emit(..)

in the child component PostCode.vue, we are printing the selected address to the console.

PostCode.vue
export default { mounted() { console.log("[SHOULD NOT NULL]", this.$refs.postarea); new window.daum.Postcode({ oncomplete: (data) => { console.log("[Selected address]", data); }, }).embed(this.$refs.postarea); }, };

create an event to pass the address the user clicked to the parent component, PostCodeApp.vue.

PostCode.vue
export default { mounted() { console.log("[SHOULD NOT NULL]", this.$refs.postarea); new window.daum.Postcode({ oncomplete: (data) => { // console.log("[selected address]", data); (-) this.$emit("address", data); // (+) }, }).embed(this.$refs.postarea); }, };
  • we've defined the event name as adress.
  • $emit('eventname', 'value to pass') - The first argument is the eventname, and the second argument is the value to pass to the parent component.

to catch the address event thrown by the child component PostCode.vue, the parent component defines a listener as shown below.

PostCode.vue
<template> <div class="postcode-demo <div class="postcode-demo"> <button @click="showPopup()">Test button</button> <PostCode v-if="visible" @address="addrSelected"/> <!-- (1) Connect the listener --> </div> </template> <script> import PostCode from "./components/PostCode.vue"; export default { components: { PostCode, }, data() { return { visible: false }; }, methods: { showPopup() { // Changing visible to true will render the PostCode component this.visible = true }, addrSelected(detail) { // (2) check the address console.log("Selected address", detail); this.visible = false; // (3) Remove the component }, }, }; </script>
  1. @address="addrSelected" - attaches the method addrSelected to handle the event address
  2. addrSelected(..) - The second argument data of the code this.$emit("address", data); that we deployed when raising the event in PostCode.vue is passed to the first argument detail of the listener addrSelected.
  3. this.visible = false - Remove PostCode.vue from the parent component as well, since the window closes when an address is selected in the address search bar.

3.5. styling

if you want to configure PostCode.vue as a layer popup, style it like below.

PostCode.vue
<template> <div class="postcode-wrap <div class="postcode-wrapper"> <! <!-- (1) Paste class "body" --> <div ref="postarea" class="body"></div> </div> </template> <script> </script export default { mounted() { new window.daum.Postcode({ width: "100%", // (2) Specify 100% width oncomplete: (data) => { this.$emit("address", data); // emit to parent }, }).embed(this.$refs.postarea); }, }; </script> </script <style .postcode-wrapper { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: #0000004d; } .postcode-wrapper .body { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: calc(100% - 20px); max-width: 500px; } </style>
  1. fill the entire area of the .postcode-wrapper with fixed. specify a slightly opaque background color (#0000004d)
  2. make the address bar 100% wide when it appears.
  3. make the .body that wraps the address bar no more than 500px wide (on large screens). on smaller screens, allow 10px left and right margins (calc(100% - 20px))

4. Result

index.html
<!DOCTYPE html> <html lang=""><! <head> <meta charset="utf-8" /> <meta http-equiv="X-UA-Compatible" content="IE=edge" /> <meta name="viewport" content="width=device-width,initial-scale=1.0" /> <link rel="icon" href="<%= BASE_URL %>favicon.ico" /> <title><%= htmlWebpackPlugin.options.title %></title> <script src="//t1.daumcdn.net/mapjsapi/bundle/postcode/prod/postcode.v2.js"></script> </head> <body> <noscript> <noscript> <strong >We're sorry but <%= htmlWebpackPlugin.options.title %> doesn't work properly without JavaScript enabled. Please enable it to continue.</strong > </noscript> <div id="app"></div> <!-- built files will be auto injected --> </body> </html>
main.js
import Vue from "vue"; import PostCodeApp from "./PostCodeApp.vue"; Vue.config.productionTip = false; new Vue({ render: (h) => h(PostCodeApp), }).$mount("#app");
PostCodeApp.vue
<template> <div class="postcode-demo <div class="postcode-demo"> <div class="postcode-demo"> <button @click="showPopup()">Test button</button> <PostCode v-if="visible" @address="addrSelected" /> <!-- (1) Connect the listener --> </div> </template> <script> import PostCode from "./components/PostCode.vue"; export default { components: { PostCode, }, data() { return { visible: false, // (+) false, start PostCode invisible }; }, methods: { showPopup() { // Changing visible to true will render the PostCode component this.visible = true; }, addrSelected(detail) { console.log("Selected address", detail); this.visible = false; }, }, }; </script>
PostCode.vue
<template> <div class="postcode-wrapper <div class="postcode-wrapper"> <div ref="postarea" class="body"></div> </div> </template> <script> </script export default { mounted() { console.log("[SHOULD NOT NULL]", this.$refs.postarea); new window.daum.Postcode({ width: "100%", oncomplete: (data) => { // context problem this! this.$emit("address", data); // emit to parent // console.log("[address]", data); }, }).embed(this.$refs.postarea); }, }; </script> <style .postcode-wrapper { position: fixed; top: 0; left: 0; right: 0; bottom: 0; background-color: #0000004d; } .postcode-wrapper .body { position: absolute; top: 50%; left: 50%; transform: translate(-50%, -50%); width: calc(100% - 20px); max-width: 500px; } </style>