I would like to use this component - I am fairly new to Vaadin14/18 (having

I would like to use this component - I am fairly new to Vaadin14/18 (having worked extensively with Vaadin 8) and would like to incorporate in a project but have not used Polymer integration. Do you have a fuller example of how to integrate with Vaadin 14/18. I assume I should follow this method ?

https://vaadin.com/docs/flow/polymer-templates/tutorial-template-basic.html

Thanks for your help.

Hi,

If you want to use the component in your Java code, you can check this chapter: https://vaadin.com/docs/v14/flow/web-components/integrating-a-web-component.html

Hi Jean-Christophe,
Thanks for your pointer. I have got this working now with Vaadin and Intellij.
Process was:

  1. Download Vaadin 18 starter
  2. Install paper-input-place using npm from the Terminal in Intellij - this installed in node_modules/paper-input-place
  3. Added PaperInputPlace class as below:

Response updated.. In order to integrate with Vaadin Flow, I have had to make some changes to the WebComponent as it was not returning the selected value correctly. This is not really a Vaadin issue, just that the WebComponent is not really ‘Vaadin ready’. The updated Vaadin Class is as follows:

import com.vaadin.flow.component.*;
import com.vaadin.flow.component.dependency.JsModule;
import com.vaadin.flow.component.dependency.NpmPackage;
import com.vaadin.flow.shared.Registration;

@Tag("paper-input-place")
@NpmPackage(value = "paper-input-place", version = "2.0.1")
@JsModule("paper-input-place/paper-input-place.js")

public class PaperInputPlace extends AbstractSinglePropertyField<PaperInputPlace, String> {
    private static final PropertyDescriptor<String,String> placeJSON = PropertyDescriptors.propertyWithDefault("placeJSON", "not entered");
    private static boolean geoReady=false;
    private static String value="not set";
    public PaperInputPlace(String k) {
        super("value", "not set", false);
        setKey(k);
        minimizeAPI(true);
    }
    public void setKey(String k)
    {
        getElement().setProperty("apiKey",k);
    }
    public void minimizeAPI(Boolean k)
    {
        getElement().setProperty("minimizeAPI", k);
    }
    public void setCountry(String countryCode) {
        getElement().setProperty("searchCountryCode",countryCode);
    }
    public void fillValue(String placeString)
    {

        // this does not need to be encoded...
        String comm = "this.fillValue($0)";
        if(geoReady) {
            getElement().executeJs(comm, placeString);
        }
        else
        {
            System.out.println("Goecoder is not yet ready: = make sure GeoReadyEvent is used:"+placeString );
        }
    }
    public String getPlace()
    {
        //this should return a string...but does not
        return placeJSON.get(this);
    }
    //
    @DomEvent("api-loaded")
    public static class GeoReadyEvent extends ComponentEvent<PaperInputPlace>
    {
        private String value;
        //was event.detail.text
        public GeoReadyEvent(PaperInputPlace source,boolean fromClient,@EventData("event.detail.text") String value)
        {
            super(source,fromClient);
            this.value=value;
            geoReady=true;
        }
    }
    public Registration addGeoReadyEventListener(ComponentEventListener<GeoReadyEvent> listener)
    {
        return addListener(GeoReadyEvent.class, listener);
    }
    //
    @DomEvent("input-change")
    public static class ValueChangeEvent extends ComponentEvent<PaperInputPlace>
    {
        private String value;
        //was event.detail.text
        public ValueChangeEvent(PaperInputPlace source,boolean fromClient,@EventData("event.detail.text") String value)
        {
            super(source,fromClient);
            this.value=value;
        }
    }
    public Registration addValueChangeEventListener(ComponentEventListener<ValueChangeEvent> listener)
    {
        return addListener(ValueChangeEvent.class, listener);
    }
    //
    @DomEvent("change-complete")
    public static class ValueCompleteEvent extends ComponentEvent<PaperInputPlace>
    {
        private String value;
        //was event.detail.text
        public ValueCompleteEvent(PaperInputPlace source,boolean fromClient,@EventData("event.detail.text") String value)
        {
            super(source,fromClient);
            this.value=value;
        }
    }
    public Registration addValueCompleteEventListener(ComponentEventListener<ValueCompleteEvent> listener)
    {
        return addListener(ValueCompleteEvent.class, listener);
    }
    @DomEvent("click")
    public static class ClickEvent extends ComponentEvent<PaperInputPlace>
    {
        private String value;
        //was event.detail.text
        public ClickEvent(PaperInputPlace source,boolean fromClient,@EventData("event.detail.text") String value)
        {
            super(source,fromClient);
            this.value=value;
        }
    }
    public Registration addClickEventListener(ComponentEventListener<ClickEvent> listener)
    {
        return addListener(ClickEvent.class, listener);
    }
}


A new event was added to the WebComponent (change-complete) because the input-change event was not returning the selected value - it was only returning what the user has typed in in the control. Also note that, If you are setting values, you have to wait until the geocoder is ready before passing values to it. Here is an example.

     PaperInputPlace p2 = new PaperInputPlace("enter key");
       // p2.fillValue("leeds, uk");
        p2.setCountry("GB");
        p2.addGeoReadyEventListener(event->
                {
                    p2.fillValue("");
                    System.out.println("API is ready "+p2.getPlace());
                }
        );
                p2.addValueCompleteEventListener(event->
                {
                    System.out.println("new value "+p2.getValue());;
                });

        Button button = new Button("Fill value");
        button.addClickListener(event->
        {
           p2.fillValue("liverpool,uk");
        });
        Button button2 = new Button("Get Values");
        button2.addClickListener(event->
        {
            Notification.show("event:"+event.getSource().getText()+", Value:" +p2.getValue()+",Place:"+p2.getPlace());
        });
        add(p2,button,button2);

Changes to the JavaScript are required a) add new function fillValue

fillValue(valueToFill)
{
//alert("fillvalue:"+valueToFill);
this.geocode(valueToFill).then(
  function(result) {
    // set the control to this place

    this.putPlace(result);
  }.bind(this),
  function(status) {
    // do something with status - the reason the geocode did not work
  //  alert("The GeoCoding API failed - Status failure:"+status)
  }.bind(this)
);
}

b) modify _onChangePlace() to include a new event change-complete

_onChangePlace(e) {
    var pl = this._places.getPlace();
    if (pl.geometry) {
      var p = this._extractPlaceInfo(pl, this.$.nativeInput.value);
      this._setPlace(p);
      this._invalid = false;
      this._setInvalid(false);
      this._setLatLng({
        lat: p.latLng.lat,
        lng: p.latLng.lng
      });
      this._value = this.$.nativeInput.value;
      this.value = {
        search: this.$.nativeInput.value,
        place_id: p.place_id,
        latLng: {
          lat: p.latLng.lat,
          lng: p.latLng.lng
        }
      };
           this.placeJSON="{ \"place\": {\"name\":\""+p.search+"\",\"latLng\":{\"lat\":"+p.latLng.lat+" ,\"long\":"+p.latLng.lng+"}}}";
          //  alert("values of placeJSON - search:"+this.placeJSON);
          //  alert("this is the new value"+this.$.nativeInput.value+":"+this.$.nativeInput.value.search);
            this.dispatchEvent(new CustomEvent('change-complete', {

                    detail: {
                      text: this.value.search
                    }
                  }));

             this.placeName=this._value.place_id;
    }
  }

I have tried to return the values back using a JavaScript variable but this does not work (but it is not necessary for correct operation).

 /**
             *provides place as a JSON string to enable returning back to Vaadin 10+
             *  name as displayed in panel and lat long
             * ***
             */
             placeJSON: {
               type: String,
               value: "not set"
             },
      /**

If you make these changes, you can

  • use Google drop down
  • return to Vaadin what has been selected by the user
  • set the values based on previous input.

It is a really useful WebComponent !

Hi, first of all thanks for a helpful comment because I am fairly new to Vaadin itself and was really hard for me to make it even appear on screen. Anyway I am running Vaadin 14 with PaperInputPlaces 2.0.1 and when I copied your code and see how it works it always gets stuck when I type first character. It looks like this https://imgur.com/HCi9rRn there are even a weird icons in it.

UPDATE:
I’ve not used proper apiKey. (was so dumb). also your comment was super useful to me I appreciate your contribution.

Ted carroll:
search: this.$.nativeInput.value,
place_id: p.place_id,
latLng: {
lat: p.latLng.lat,
lng: p.latLng.lng
}

I’m trying to extract “Country, Street, Street Number, Lat, Lng” but unfortunately I don’t know how. I know I should probably try to extract it from “var p = this._extractPlaceInfo(pl, this.$.nativeInput.value);”
But it is difficult for me I’m a real beginner in JS.

You should get a string using getValue which is in JSON using the CompleteEventListener

p2.addValueCompleteEventListener(event->
{
System.out.println("new value "+p2.getValue());;
});

search":"81 Headingley Lane, Headingley, Leeds, UK","place_id":"Ei84MSBIZWFkaW5nbGV5IExuLCBIZWFkaW5nbGV5LCBMZWVkcyBMUzYgMkRILCBVSyIwEi4KFAoSCUdcUthLWXlIEUH2mbYRf-RlEFEqFAoSCcPyO7FNWXlIEdWwqslFhGQz","latLng":{"lat":53.8189731,"lng":-1.5751613}}

You can map this to a Object in Java - was that your question?

Yes that helped a lot! And If I may ask one more question. Is there any way I can setValue for it ?

Example: I get in my url …/Paris?lat=…?lng=…/…
And in paper-input-place i set value “Paris, France” so that is clear for user that his selection is in use ?

The only way I could get it to work with Vaadin is using the fillValue function as shown above - you have to provide a valid Google address and then it will geocode and asdd to the component.