InputPlace wraps Google Places or Azure Maps AutoComplete functionality to give your applications type-ahead place search. Based on Google Places AutoComplete by Google.
The autocomplete service matches full words and substrings and resolves place names, addresses and plus codes. You must include the <script> with your Google API Key.
Autocomplete is a feature of the Places library in the Maps JavaScript API. You can use autocomplete to give your applications the type-ahead-search behavior of the Google Maps search field. The autocomplete service can match on full words and substrings, resolving place names, addresses, and plus codes. Applications can therefore send queries as the user types, to provide on-the-fly place predictions.
InputPlace can also be backed by Azure Maps Search by Microsoft, see the Azure page.
<div class="card">
<h5>Google Address Form</h5>
<p>The autocomplete service matches full words and substrings and resolves place names, addresses and plus codes. You must include the <code><script></code> with your <strong>Google API Key</strong>.</p>
<script async="true" defer="defer" src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCvCDkYieuUBmMWon_mfLAfjuaeuosuqow&loading=async&libraries=places"></script>
<h:form id="formGoogleUsage">
<p:growl id="growl" showDetail="true" showSummary="true" globalOnly="false"/>
<div jsf:id="inputGroup" class="field grid">
<p:outputLabel for="txtPlace" value="Location:" styleClass="col-12 md:col-1"/>
<div class="col-12 md:col-6">
<div class="p-inputgroup">
<div class="p-inputgroup-addon"><i class="fa-solid fa-location-dot"></i></div>
<pe:inputPlace id="txtPlace" widgetVar="place" value="#{basicInputPlaceController.input}" required="true"
placeholder="Enter a location" styleClass="w-full" restrictCountries="us,ca">
<p:ajax event="placeChanged" listener="#{basicInputPlaceController.onPlaceChanged}" update="selectedPlace growl"/>
</pe:inputPlace>
</div>
</div>
<div class="col-12 md:col-2">
<p:commandButton value="Search" actionListener="#{basicInputPlaceController.submit}" update="inputGroup growl"/>
</div>
</div>
<div jsf:id="selectedPlace">
<p:card rendered="#{basicInputPlaceController.selectedPlace != null}">
<f:facet name="title">
Type: #{basicInputPlaceController.selectedPlace.types}
</f:facet>
<p:divider/>
<div class="formgrid grid">
<div class="field col-12 md:col-4">
<label>Place ID</label>
<p:inputText value="#{basicInputPlaceController.selectedPlace.placeId}" readonly="true" styleClass="w-full"/>
</div>
<div class="field col-12 md:col-4">
<label>Latitude</label>
<p:inputText value="#{basicInputPlaceController.selectedPlace.latitude}" readonly="true" styleClass="w-full"/>
</div>
<div class="field col-12 md:col-4">
<label>Longitude</label>
<p:inputText value="#{basicInputPlaceController.selectedPlace.longitude}" readonly="true" styleClass="w-full"/>
</div>
<div class="field col-12">
<label>Formatted Address</label>
<p:inputText value="#{basicInputPlaceController.selectedPlace.formattedAddress}" readonly="true" styleClass="w-full"/>
</div>
<div class="field col-12 md:col-6">
<label>Name</label>
<p:inputText value="#{basicInputPlaceController.selectedPlace.name}" readonly="true" styleClass="w-full"/>
</div>
<div class="field col-12 md:col-6">
<label>Address Line</label>
<p:inputText value="#{basicInputPlaceController.selectedPlace.addressLine}" readonly="true" styleClass="w-full"/>
</div>
<div class="field col-12 md:col-3">
<label>City</label>
<p:inputText value="#{basicInputPlaceController.selectedPlace.city}" readonly="true" styleClass="w-full"/>
</div>
<div class="field col-12 md:col-3">
<label>State/Province</label>
<p:inputText value="#{basicInputPlaceController.selectedPlace.state}" readonly="true" styleClass="w-full"/>
</div>
<div class="field col-12 md:col-3">
<label>Country</label>
<p:inputText value="#{basicInputPlaceController.selectedPlace.country}" readonly="true" styleClass="w-full"/>
</div>
<div class="field col-12 md:col-3">
<label>Zip/Postal Code</label>
<p:inputText value="#{basicInputPlaceController.selectedPlace.postalCode}" readonly="true" styleClass="w-full"/>
</div>
<div class="field col-12 md:col-6">
<label>Area 2</label>
<p:inputText value="#{basicInputPlaceController.selectedPlace.administrativeAreaLevel2}" readonly="true" styleClass="w-full"/>
</div>
<div class="field col-12 md:col-6">
<label>Area 3</label>
<p:inputText value="#{basicInputPlaceController.selectedPlace.administrativeAreaLevel3}" readonly="true" styleClass="w-full"/>
</div>
</div>
</p:card>
</div>
</h:form>
</div>
package org.primefaces.extensions.showcase.controller.inputplace;
import java.io.Serial;
import java.io.Serializable;
import jakarta.faces.application.FacesMessage;
import jakarta.faces.context.FacesContext;
import jakarta.faces.view.ViewScoped;
import jakarta.inject.Named;
import org.primefaces.event.SelectEvent;
import org.primefaces.extensions.model.inputplace.Place;
@Named
@ViewScoped
public class BasicInputPlaceController implements Serializable {
@Serial
private static final long serialVersionUID = 1L;
private String input;
private Place selectedPlace;
private String azureApiKey;
public void submit() {
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Place", input));
}
public void onPlaceChanged(final SelectEvent<Place> event) {
this.selectedPlace = event.getObject();
FacesContext context = FacesContext.getCurrentInstance();
context.addMessage(null, new FacesMessage(FacesMessage.SEVERITY_INFO, "Selected Place", selectedPlace.toString()));
}
public String getInput() {
return input;
}
public void setInput(String input) {
this.input = input;
}
public Place getSelectedPlace() {
return selectedPlace;
}
public void setSelectedPlace(Place selectedPlace) {
this.selectedPlace = selectedPlace;
}
public String getAzureApiKey() {
return azureApiKey;
}
public void setAzureApiKey(String azureApiKey) {
this.azureApiKey = azureApiKey;
}
}