0

I am trying to develop an admin panel for my project. In this project there is an entity named Places which will store data about stores and malls. To make usage easier, i want a search field to search on Google Maps and retrieve coordinates directly from Google Maps. There is a tiny but powerful react component for this, react-geosuggest Now i want to use this component in my Easy Admin new and edit forms. But i couldn't solve how should i achieve this?

I tried to add a customized field to symfony but it is not working (documentation about this). Also tried to just customize appearance but this is not working, too.

bahadir arslan
  • 4,535
  • 7
  • 44
  • 82

1 Answers1

0

At least i succeeded to implement this feature. Here is how i made it.

Firstly i added react-geosuggest code to assets/js folder in geosuggest.jsx

import React from 'react';
import ReactDOM from 'react-dom';
import Geosuggest from 'react-geosuggest';
class App extends React.Component {
    /**
     * Render the example app
     */
    render() {
      var fixtures = [];

      return (
        <div>
          <Geosuggest
            ref={el=>this._geoSuggest=el}
            placeholder="Start typing!"
            fixtures={fixtures}
            onSuggestSelect={this.onSuggestSelect}
            location={new google.maps.LatLng(53.558572, 9.9278215)}
            radius="20" />

        </div>
      )
    }

    /**
     * When a suggest got selected
     * @param  {Object} suggest The suggest
     */
    onSuggestSelect(suggest) {
      document.getElementById('places_coordinates').value = suggest.location.lat + "," + suggest.location.lng;
      document.getElementById('places_address').value = suggest.gmaps.formatted_address;
      document.getElementById('geosuggest-help').innerHTML += ": "+ suggest.location.lat + "," + suggest.location.lng;
      console.log(suggest.location.lat + "," + suggest.location.lng);
      console.log(suggest.gmaps.formatted_address);
      console.log(suggest);
    }
  }

  ReactDOM.render(<App />, document.getElementById('google_map'));

To get location and address information from react component, i added some codes in onSuggestSelect function

 document.getElementById('places_coordinates').value = suggest.location.lat + "," + suggest.location.lng;
      document.getElementById('places_address').value = suggest.gmaps.formatted_address;
      document.getElementById('geosuggest-help').innerHTML += ": "+ suggest.location.lat + "," + suggest.location.lng;

Then i added this file to webpack-config.js file

.addEntry('react','./assets/js/geosuggest.jsx')

In easy_admin.yaml file i declared the field which i want to add geosuggest functionality

 - { property: 'coordinates', icon: 'user', label: 'Coordinates', help: null, type: 'text', type_options: { block_name: 'geosuggest' }  }

Also i added template for new entity html with this code

templates:
                    new: 'admin/new-place.html.twig'

So i created new-place.html.twig file in templates/admin folder.

{# templates/new-place.html.twig #}
{% extends '@EasyAdmin/default/new.html.twig' %}
{% block body_javascript %}
   {{ parent() }}

<script type="text/javascript" src="{{ asset('build/runtime.js') }}"></script>
{% endblock %}

This block_name is the magic attribute; with this attribute i am able to customize field. So i created a file in templates/form folder named geosuggest.html.twig. Here is the source of this file

{# templates/form/fields.html.twig #}
{% block _places_geosuggest_widget %}
<style>
.geosuggest {

    position: relative;
    width: 70%;

    text-align: left;
  }
  .geosuggest__input {
    width: 100%;
    border: 2px solid transparent;
    box-shadow: 0 0 1px #3d464d;
    padding: .1em .5em;
    -webkit-transition: border 0.2s, box-shadow 0.2s;
            transition: border 0.2s, box-shadow 0.2s;
  }
  .geosuggest__input:focus {
    border-color: #267dc0;
    box-shadow: 0 0 0 transparent;
  }
  .geosuggest__suggests {
    position: absolute;
    top: 100%;
    left: 0;
    right: 0;
    max-height: 25em;
    padding: 0;
    margin-top: -1px;
    background: #fff;
    border: 2px solid #267dc0;
    border-top-width: 0;
    overflow-x: hidden;
    overflow-y: auto;
    list-style: none;
    z-index: 5;
    -webkit-transition: max-height 0.2s, border 0.2s;
            transition: max-height 0.2s, border 0.2s;
  }
  .geosuggest__suggests--hidden {
    max-height: 0;
    overflow: hidden;
    border-width: 0;
  }

  /**
   * A geosuggest item
   */
  .geosuggest__item {
    font-size: 18px;
    font-size: 1rem;
    padding: .5em .65em;
    cursor: pointer;
  }
  .geosuggest__item:hover,
  .geosuggest__item:focus {
    background: #f5f5f5;
  }
  .geosuggest__item--active {
    background: #267dc0;
    color: #fff;
  }
  .geosuggest__item--active:hover,
  .geosuggest__item--active:focus {
    background: #ccc;
  }
  .geosuggest__item__matched-text {
    font-weight: bold;
  }

  </style>
<div id="google_map"></div>
 {% if help is defined %}
        <span class="help-block" id="geosuggest-help">Mekanın koordinatları</span>
    {% endif %}
<script src="https://maps.googleapis.com/maps/api/js?key=YOURGOOGLEAPIKEY&libraries=places"></script>
<script type="text/javascript" src="{{ asset('build/react.js') }}"></script>
<input type="hidden" id="places_coordinates" name="places[coordinates]" required="required" class="form-control form-control">
 {% endblock %}

Normally easyadmin would generate a text field for coordinates field but react code will delete this input field and replace it with own textbox. To get coordinate data and pass it to easyadmin while saving i used a hidden field. Which you can see above code.

And it worked.

Probably it is not the best approach but this is the only way that i found to make it work. Hope this helps you.

bahadir arslan
  • 4,535
  • 7
  • 44
  • 82