Tuesday, May 21, 2024
HomeRuby On RailsGoogle Maps API with StimulusJS

Google Maps API with StimulusJS


# Terminal
rails g scaffold locations title latitude:decimal longitude:decimal
rails webpacker:set up:stimulus
# layouts/utility.html.erb
<%= javascript_include_tag "https://maps.googleapis.com/maps/api/js?key=#{ENV['MAPS_API_KEY']}&libraries=locations&callback=dispatchMapsEvent",
                            async: true,
                            defer: true,
                            "data-turbolinks-eval": false %>
# packs/utility.js
window.dispatchMapsEvent = perform (...args) {
  const occasion = doc.createEvent("Occasions")
  occasion.initEvent("google-maps-callback", true, true)
  occasion.args = args
  window.dispatchEvent(occasion)
}
# javascript/controllers/maps_controller.js
import { Controller} from "stimulus"

export default class extends Controller {
  static targets = ["field", "map", "latitude", "longitude"]

  join() {
    if (typeof (google) != "undefined"){
      this.initializeMap()
    }
  }

  initializeMap() {
    this.map()
    this.marker()
    this.autocomplete()
    console.log('init')
  }

  map() {
    if(this._map == undefined) {
      this._map = new google.maps.Map(this.mapTarget, {
        middle: new google.maps.LatLng(
          this.latitudeTarget.worth,
          this.longitudeTarget.worth
        ),
        zoom: 17
      })
    }
    return this._map
  }

  marker() {
    if (this._marker == undefined) {
      this._marker = new google.maps.Marker({
        map: this.map(),
        anchorPoint: new google.maps.Level(0,0)
      })
      let mapLocation = {
        lat: parseFloat(this.latitudeTarget.worth),
        lng: parseFloat(this.longitudeTarget.worth)
      }
      this._marker.setPosition(mapLocation)
      this._marker.setVisible(true)
    }
    return this._marker
  }

  autocomplete() {
    if (this._autocomplete == undefined) {
      this._autocomplete = new google.maps.locations.Autocomplete(this.fieldTarget)
      this._autocomplete.bindTo('bounds', this.map())
      this._autocomplete.setFields(['address_components', 'geometry', 'icon', 'name'])
      this._autocomplete.addListener('place_changed', this.locationChanged.bind(this))
    }
    return this._autocomplete
  }

  locationChanged() {
    let place = this.autocomplete().getPlace()

    if (!place.geometry) {
      // Consumer entered the title of a Place that was not urged and
      // pressed the Enter key, or the Place Particulars request failed.
      window.alert("No particulars out there for enter: '" + place.title + "'");
      return;
    }

    this.map().fitBounds(place.geometry.viewport)
    this.map().setCenter(place.geometry.location)
    this.marker().setPosition(place.geometry.location)
    this.marker().setVisible(true)

    this.latitudeTarget.worth = place.geometry.location.lat()
    this.longitudeTarget.worth = place.geometry.location.lng()
  }

  preventSubmit(e) {
    if (e.key == "Enter") { e.preventDefault() }
  }
}
# views/locations/_form.html.erb
<%= form_with mannequin: place, native: true, knowledge: {
                                            controller: :maps,
                                            motion: "[email protected]>maps#initializeMap"
                                          } do |kind| %>
  <div class="area">
    <%= kind.label :title %>
    <%= kind.text_field :title, class: 'form-control' %>
  </div>

  <div class="area">
    <%= kind.label :search %>
    <%= kind.search_field :search, title: nil, class: 'form-control', knowledge: { goal: "maps.area", motion: "keydown->maps#preventSubmit" } %>
  </div>

  <div class="area">
    <%= kind.label :latitude %>
    <%= kind.text_field :latitude, class: 'form-control', knowledge: { goal: "maps.latitude" } %>
  </div>

  <div class="area">
    <%= kind.label :longitude %>
    <%= kind.text_field :longitude, class: 'form-control', knowledge: { goal: "maps.longitude" } %>
  </div>

  <%= content_tag :div, nil, knowledge: { goal: "maps.map" }, class: 'map' %>

  <div class="actions">
    <%= kind.submit class: 'btn btn-primary' %>
  </div>
<% finish %>
# stylesheets/locations.scss
.map {
  width: 100%;
  min-height: 400px;
}
# views/locations/present.html.erb
<%= image_tag "https://maps.googleapis.com/maps/api/staticmap?zoom=15&dimension=400x300&middle=#{@place.latitude},#{@place.longitude}&key=#{ENV['MAPS_API_KEY']}", alt: "Map" %>
RELATED ARTICLES

LEAVE A REPLY

Please enter your comment!
Please enter your name here

Most Popular

Recent Comments