ERPNext Conference 2019* ERPNext.com Blog

Is there a way to create a new field type?

custom_field
doctype

#2

Hello,

This is not configurable for now. You can develop and contribute in field type in Frappe Framework. If required field type is not available, you can also create a Github Issue for it.


#3

Thanks for responding.
I would like to have a map picker where users can move a pin on the map to specify a location. I would like to store the latitude and the longitude of the pin. This might not be suitable to be part of the core ERPNext since it will need to load extra js library which might not be needed by the whole community. So, I suggest it being done in the app level if possible.


#4

I think you can do it. In your doctype create two float docfields for latitude and longitude. The API of your map application can probably report the long and lat to you after you’ve moved it, which you can store in the in the docfields. There’s some administrative PITA you’ll need to do of course.
Also, your concern about an outside library and an app level integration I think is an excellent instinct.
Good luck @dalwadani, PM me if you want to do a code review or something. I think this is achievable.


#5

@dalwadani These apps may help you:



#6

A guide how to add a custom type in general is needed.

Mapping should be part of the core.


#7

Refer this PR


How to install modules automatically
#8

I think it can be done using HTML field type. However, I wish there is a standard way to add custom fields and localise it to the app.


#9

This PR changes the core which something I am not comfortable doing.


#10

I think of it differently: HTML fields are just a layer of functionality down from regular docfields. Docfields are just regular HTML text input fields with additional functionality, everything uses HTML as a base, there isn’t some weird TKL injection or something. To get rich functionality out of HTML in Frappe/ERPNext is work, sometimes a lot of it.

@revant_one and his team member @gvrvnk at MN Technique are experts at this and they’ve helped me a lot with my application. Consider retaining their services, direct or consultative, to help put you over the top.


#11

Send a PR?
Map field will be a great feature for everyone.

Reference :
http://geojson.org - store map data as geojson python, js libs available
Free an open source Map selection view http://leafletjs.com
I guess Google Maps will require API key and their own js lib.


#12

I agree, I think a map doctype should be a core docfield type, and I second the GeoJSON suggestion. Several others have implemented their own versions, but I don’t love the idea of relying on a third party API key - it’s just another thing for a new user to set up in process that is already approaching being overly burdensome.


#13

@revant_one

Your two link refer as guide to add new Field ?


#14

This HTML and leaflet maps has my initial try a few month ago . I can identify the following issues with this approach

  1. Refresh of the field coordinates based on Doctype Properties is can not be optiomized. Example is add row of Child Table you need to catch several events.
  2. HTML render_template is not good . The rendering syntax (as I know) is some jinja templating hack.
  3. Map pointer properties like coloring are also an issue.

#15

While using a HTML field is not optimal, it is still the best compromise I see since changes can be local to the app. However, if the same field is used in more than one place, you will need to have multiple copy of the same logic violating DRY principle.
This is what I was able to accomplish using HTML:


ERPNext for Agriculture and ERPNext spatially enable
#16

@dalwadani I’m having trouble getting my map to render, could you share your code? Are you using frappe.render_template?


#17

I didn’t use render_template. I added a custom HTML field with value of: <div id="map_canvas"></div>
Then, in the js files:

frappe.ui.form.on("DOCTYPE_NAME", {
  refresh: function(frm) {
    frappe.require("/assets/APP_NAME/js/init_map.js", function() {
      $.getScript(
        "https://maps.googleapis.com/maps/api/js?key=XXX&libraries=places&callback=initMap"
      );
    });
  }
});

in init_map.js:

function initMap() {
var mapOptions = {
zoom: 14,
center: new google.maps.LatLng(LAT, LNG),
mapTypeId: google.maps.MapTypeId.ROADMAP
};
map = new google.maps.Map(document.getElementById(“map_canvas”), mapOptions);
$("

")
.addClass(“centerMarker”)
.appendTo(map.getDiv());
map.addListener(“center_changed”, function() {
cur_frm.set_value(“latitude”, map.center.lat());
cur_frm.set_value(“longitude”, map.center.lng());
});
// Create the search box and link it to the UI element.
var input = document.getElementById(‘pac-input’);
var searchBox = new google.maps.places.SearchBox(input);
map.controls[google.maps.ControlPosition.TOP_LEFT].push(input);

// Bias the SearchBox results towards current map’s viewport.
map.addListener(‘bounds_changed’, function() {
searchBox.setBounds(map.getBounds());
});

// Listen for the event fired when the user selects a prediction and retrieve
// more details for that place.
searchBox.addListener(‘places_changed’, function() {
var places = searchBox.getPlaces();

if (places.length == 0) {
  return;
}

// For each place, get the icon, name and location.
var bounds = new google.maps.LatLngBounds();
places.forEach(function(place) {
  if (place.geometry.viewport) {
    // Only geocodes have viewport.
    bounds.union(place.geometry.viewport);
  }
});
map.fitBounds(bounds);

});
}


#18

@dalwadani Very nice approach.

Unfortunately I still can not find a clear guide for this and need map field also.

@revant_one shared links weren’t so helpfull in my case to clear it up and make a guide.


#19

It is coming to core soon I hope, see this pull request https://github.com/frappe/frappe/pull/4327


#20

During the conference @pratu16x7 and @netchampfaris added a barcode field.

I took that and signature field as reference.

It is combination of Leaflet, Leaflet Draw, Leaflet Locate, frappe documentation, google searches landing to gis.stackexchange.com and some github issues where they discussed code workarounds.

Test the pull request. It is working.

  • Drawing layers are loaded from saved data.
  • Layers are editable.
  • Layers are being saved (all added layers)

Only issue I’m facing right now is in draw:created binding the created layer is added twice.
I’m working on it. Check if you can do something.

How to test:

  1. switch to map_control branch
  2. add Map field (2 or more fields for testing) to custom doctype or add custom map field.
  3. all you have to change is controls/map.js and test in browser / console.

#21

Ty @revant_one for you reply.
I have already checked your PR in my local :slight_smile: . I will try to help or review someparts (document function etc). It’s only matter of finding the free time.