Pada sesi sebelumnya kita telah mempelajari bagaimana cara instalasi Google Maps v3 pada aplikasi Rails yang kita buat dan juga field autocomplete dengan menggunakan jQuery Flexbox.
Sesi kali ini akan membahas kasus lain dari google maps dan pointing lokasi berdasarkan input nama daerah atau lebih dikenal dengan nama geocode. Sebagai contoh di sini provinsi dan nama kota berasal dari Indonesia.
Misalkan kita input Jawa Barat sebagai provinsi dan Bandung sebagai nama kotanya, maka google maps akan pointing ke kota Bandung provinsi Jawa Barat.
Pertama kita buat model user yang berisi nama serta informasi lokasinya
Misalkan kita input Jawa Barat sebagai provinsi dan Bandung sebagai nama kotanya, maka google maps akan pointing ke kota Bandung provinsi Jawa Barat.
Pertama kita buat model user yang berisi nama serta informasi lokasinya
rails g model user name:string city_name:string state_name:string country_name:string
Untuk memuat data lokasi sebagai opsi, buat juga model city dan statenya
rails g model city name:string state_id:integer
rails g model state name:string
dan rake db:migrate
Setelah itu buat relasi antara city dan state
app/models/city.rb
class City > ActiveRecord::Base
belongs_to :state
end
belongs_to :state
end
app/models/state.rb
class State > ActiveRecord::Base
has_many :cities
end
has_many :cities
end
Relasi antara state dan city akan memudahkan untuk populate nama kota berdasarkan nama provinsinya masing-masing. Untuk mempermudah dalam membuat data state dan city, tambahkan di app/db/seeds.rb
State.create(
[
{:name => "West Java"},
{:name => "Central Java"},
{:name => "East Java"}
]
)
#City
country = Country.find_by_name("Indonesia")
west_java = State.find_by_name("West Java")
central_java = State.find_by_name("Central Java")
east_java = State.find_by_name("East Java")
City.create(
[
{:name => "Bandung", :state_id => "#{west_java.id}"},
{:name => "Bogor", :state_id => "#{west_java.id}"},
{:name => "Sukabumi", :state_id => "#{west_java.id}"},
{:name => "Semarang", :state_id => "#{central_java.id}"},
{:name => "Kudus", :state_id => "#{central_java.id}"},
{:name => "Demak", :state_id => "#{central_java.id}"},
{:name => "Surabaya", :state_id => "#{east_java.id}"},
{:name => "Lamongan", :state_id => "#{east_java.id}"},
{:name => "Tulungagung", :state_id => "#{east_java.id}"}
]
)
Lalu jalankan di console rake db:seed Setelah langkah-langkah di atas baru kita bisa mulai membuat bagian view nya. Misal kita akan membuat user baru beserta data lokasinya. Buat method di app/controllers/users_controller.rb untuk halaman create user.
def new
@user = User.new
end
private
def prepare_state
@states = State.all.map{|x|x.name}.unshift(['Please select', ''])
end
Lalu buat app/views/users/new.html.erb yang berisi form untuk create user : <script type="text/javascript"
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyAVdlyqpDfn1sXmYcY9WJS4cfU0jnkIWao&sensor=false">
</script>
<script type="text/javascript">
function initialize() {
var mapOptions = {
center: new google.maps.LatLng(-7.2099,110.606918),
zoom: 3,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
var map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
}
google.maps.event.addDomListener(window, 'load', initialize);
$(document).ready(function(){
initialize();
})
</script>
<%= form_for @user do |form| %>
<%= form.label :name %> <%= form.text_field :name %>
<br />
<div class="locations">
<%= form.label :state_name, "Provinsi" %> <%= form.select :state_name, options_for_select(@states) %>
<br />
<%= form.label :city_name, "Kota" %> <div id="city_name"></div>
<%= form.hidden_field :city_name %>
</div>
<br />
<div id="map-canvas" style="width:300px;height:200px"/>
<%end%>
View di atas masih berupa form create user dan google maps saja.
Untuk pointing lokasi di map berdasarkan input diperlukan beberapa fungsi javascript untuk trigger ketika dropdown provinsi dipilih. Input nama kota di atas juga menggunakan jquery flexbox untuk autocomplete yang telah dibahas pada sesi sebelumnya.
Fungsi trigger untuk pointing lokasi di map berdasarkan input provinsi diambil contoh seperti ini
<script type="text/javascript">
$(document).ready(function(){
$("#user_state_name").on("change", function(){
set_map($(this).val());
});
function set_map(city,state,country){
var mapOptions = {
center: new google.maps.LatLng(-7.2099,110.606918),
zoom: 7,
mapTypeId: google.maps.MapTypeId.ROADMAP
};
country = "Indonesia";
var map = new google.maps.Map(document.getElementById("map-canvas"),
mapOptions);
if(city == ''){
address = state + ',' + "Indonesia"
}else{
address = city + ',' + state + ',' + "Indonesia"
}
var geocoder = new google.maps.Geocoder();
geocoder.geocode({
'address':address
},
function(result, status){
if (status == google.maps.GeocoderStatus.OK){
map.setCenter(result[0].geometry.location);
var marker = new google.maps.Marker({
map: map,
position: result[0].geometry.location
});
}else{
alert("Geocode was not successful for the following reason: " + status);
}
});
return false;
}
</script>
Selain pointing lokasi, ketika dropdown provinsi dipilih juga akan populate nama kota di bawah provinsi tersebut. Agar data provinsi dan kota sesuai maka diperlukan relasi antara keduanya serta AJAX untuk merequest perubahan data city berdasarkan state yang dipilih.
Pertama kita tambahkan buat method populate_cities di app/controllers/users_controller.rb. Method tersebut hanya untuk load halaman partial untuk meload kembali form user tapi dengan catatan field city yang sudah berisi data city sesuai state yang dipilih.
def populate_cities
render :layout => false
end
Setelah itu buat fungsi javascript untuk populate_cities ketika dropdown provinsi dipilih
$(document).ready(function(){
$("#user_state_name").on("change", function(){
populate_cities();
set_map($(this).val());
function populate_cities(){
var base_address = $(".locations");
var controller = "<%= populate_cities_users_path %>";
$.ajax({
type: "GET",
url: escape(controller),
data: {"state_name" : $('#user_state_name').val()},
dataType:"html",
beforeSend:function(){
$('#city_name_input').attr('disabled', 'disabled').css('background-color', '#E6E6E6');
},
success:function(data){
jQuery(".locations").html(data);
}
})
}
});
Ketika fungsi tersebut di-execute maka akan merender halaman partial tanpa harus meload ulang satu halaman untuk populate data city. Buat halaman partial sesuai nama method populate_cities (app/views/users/populate_cities.erb). Pada halaman partial tersebut juga disertakan fungsi javascript untuk autocomplete nama kotanya.
Berikut ini adalah hasil dari geocode yang sudah terintegrasi dengan rails :
Selamat mencoba dan happy coding :)
<script type="text/javascript">
function cities_flexbox(){
var query = "<%= @city_name %>";
jQuery("#city_name").flexbox('<%= autocomplete_city_users_path %>',{
customParameters: {q: query, state_name: $('#user_state_name').val()},
method: 'post',
watermark: query,
showArrow: false,
inputClass: 'inpu',
minChars: 2,
width:200,
queryDelay: 300,
paging:true,
highlightMatches:true,
containerClass:'ffbContainer',
onSelect: function(){
$("#user_city_name").attr('value', this.getAttribute('hiddenValue'));
set_map($("#user_city_name").val(),$("#user_state_name").val(),'Indonesia');
}
});
}
$(function(){
cities_flexbox();
});
</script>
<label>Provinsi :</label>
<%= select_tag 'user[state_name]', options_for_select(@states, params[:state_name]) %>
<br />
<label>Kota :</label>
<div id="city_name"></div>
<%= hidden_field_tag "user[city_name]" %>
Fungsi cities_flexbox()di atas merupakan fungsi javascript untuk meload field input autocomplete. Ketika field input autocomplete diisi nama city maka akan muncul datanya sesuai dengan keywordnya dan ketika dipilih maka google maps akan pointing lokasi berdasarkan state dan city nya. Berikut ini adalah hasil dari geocode yang sudah terintegrasi dengan rails :