I thought as I have Leaflet working well I would share some code to get people started if you want to use Leaflet in Wappler. Hopefully it will be integrated at some point, but it's not too complicated to code. I did a quick db so don't judge me if I don't have field types/indexes set up properly
First the tables. I have two for this example. One for the markers and one for the map icons (I'm using MapMarker to create the icons - a fantastic free resource). You'll, need to set up the database tables in your database and create the server connects - get_icons and get_markers.
There are no API keys needed for this as it's using Open Street Maps. To use other map tiles and for more options, see the documentation at https://leafletjs.com/
MARKERS
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for tbl_markers
-- ----------------------------
DROP TABLE IF EXISTS `tbl_markers`;
CREATE TABLE `tbl_markers` (
`marker_id` int(11) NOT NULL AUTO_INCREMENT,
`icon_id` int(11) NOT NULL,
`title` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL,
`lat` decimal(10, 4) NOT NULL,
`lng` decimal(10, 4) NOT NULL,
`description` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
PRIMARY KEY (`marker_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of tbl_markers
-- ----------------------------
INSERT INTO `tbl_markers` VALUES (1, 1, 'Test 1', 42.3691, 42.3691, 'Test One Description');
INSERT INTO `tbl_markers` VALUES (2, 2, 'Test 2', 50.8503, 50.8503, 'Test Two Description');
INSERT INTO `tbl_markers` VALUES (3, 3, 'Test 3 ', 50.8369, 50.8369, 'Test Three Description');
INSERT INTO `tbl_markers` VALUES (4, 2, 'Test 4', 49.4076, 49.4076, 'Test Four (same icon as 2');
SET FOREIGN_KEY_CHECKS = 1;
ICONS
SET NAMES utf8mb4;
SET FOREIGN_KEY_CHECKS = 0;
-- ----------------------------
-- Table structure for tbl_icons
-- ----------------------------
DROP TABLE IF EXISTS `tbl_icons`;
CREATE TABLE `tbl_icons` (
`icon_id` int(11) NOT NULL AUTO_INCREMENT,
`icon_url` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT NULL,
PRIMARY KEY (`icon_id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 5 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of tbl_icons
-- ----------------------------
INSERT INTO `tbl_icons` VALUES (1, 'https://cdn.mapmarker.io/api/v1/pin?size=120&background=%23373737&icon=fa-star&color=%23C45100&voffset=0&hoffset=1&');
INSERT INTO `tbl_icons` VALUES (2, 'https://cdn.mapmarker.io/api/v1/pin?size=120&background=%23FCC400&icon=fa-star&color=%23C45100&voffset=0&hoffset=1&');
INSERT INTO `tbl_icons` VALUES (3, 'https://cdn.mapmarker.io/api/v1/fa?size=120&icon=fa-star&color=%23C45100&');
INSERT INTO `tbl_icons` VALUES (4, 'https://cdn.mapmarker.io/api/v1/fa/stack?size=120&icon=fa-star&color=%23194D33&on=fa-circle&oncolor=%23FCDC00&hoffset=1&voffset=0&iconsize=35&');
SET FOREIGN_KEY_CHECKS = 1;
THE HEADERS
I can't seem to paste the whole code all at once so here is the head section
<head>
<base href="/">
<script src="dmxAppConnect/dmxAppConnect.js"></script>
<meta charset="UTF-8">
<title>Leaflet Example</title>
<link rel="stylesheet" href="fontawesome4/css/font-awesome.min.css" />
<meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
<link rel="stylesheet" href="bootstrap/4/united/bootstrap.min.css" />
<link rel="stylesheet" href="https://unpkg.com/leaflet@1.7.1/dist/leaflet.css" integrity="sha512-xodZBNTC5n17Xt2atTPuE1HxjVMSvLVW9ocqUKLsCC5CXdbqCmblAshOMAS6/keqq/sMZMZ19scR4PsZChSR7A==" crossorigin="" />
<!-- Make sure you put this AFTER Leaflet's CSS -->
<script src="https://code.jquery.com/jquery-3.5.1.min.js" integrity="sha384-ZvpUoO/+PpLXR1lu4jmpXWu80pZlYUAfxl5NsBMWOEPSjUn/6Z/hRTt8+pR6L4N2" crossorigin="anonymous"></script>
<script src="https://unpkg.com/leaflet@1.7.1/dist/leaflet.js" integrity="sha512-XQoYMqMTK8LvdxXYG3nZ448hOEQiglfqkJs1NOQV44cWnUrBc8PkAOcXy20w0vlaXaVUearIOBhiXZ5V3ynxwA==" crossorigin=""></script>
THE CODE
<body is="dmx-app" id="leaflet">
<dmx-serverconnect id="sc_icons" url="dmxConnect/api/Leaflet/get_icons.php"></dmx-serverconnect>
<dmx-serverconnect id="sc_markers" url="dmxConnect/api/Leaflet/get_markers.php" onsuccess="setMapMarkers();"></dmx-serverconnect>
<div id="mapid" style="height:800px;"></div> <!--Your DIV must have a height!!-->
<script>
//LEAFLET CODE
//Main Map initialization
var map = L.map('mapid', {
fullscreenControl: true,
tap:false,
touchZoom: true,
fullscreenControlOptions: {
position: 'topleft'
},
center: [41.6510,0.878195],
zoom: 5});
L.tileLayer('https://api.mapbox.com/styles/v1/{id}/tiles/{z}/{x}/{y}?access_token=pk.eyJ1IjoiaGV6bWFubiIsImEiOiJjajhvOXN3OWEwMThvMndudGZoYzF0aTR0In0.oI4Z-bC2IM63PxoSNwwD2g', {
attribution: 'Map data © <a href="https://www.openstreetmap.org/">OpenStreetMap</a> contributors, <a href="https://creativecommons.org/licenses/by-sa/2.0/">CC-BY-SA</a>, Imagery © <a href="https://www.mapbox.com/">Mapbox</a>',
maxZoom: 18,
id: 'mapbox/streets-v11',
}).addTo(map);
//Make the Marker Icons from tbl_icons
function makeIcons(){
var icons = dmx.parse('sc_icons.data.query');
if (Array.isArray(icons)){
icons.forEach(function(icon){
var thisURL = icon.icon_url;
window['icon'+icon.icon_id] = L.icon({iconUrl: thisURL, iconAnchor: [16, 32], popupAnchor: [-16, -32]});
});
}else{
}
}
markersLayer = new L.FeatureGroup(); //Create the Markers Layer
//Create the map markers and pop up cards and add to main map
//**MAKE SURE YOU ARE CALLING THIS IN YOUR SERVER CONNECT onsuccess() FOR THE MARKERS**//
function setMapMarkers() {
markersLayer.clearLayers();
bounds = L.latLngBounds();
//creates custom icons from tbl_icons, see above
makeIcons();
//get our markers from tbl_markers. If you filter the server connect this will automatically be filtered as well. Nifty!
var markers = dmx.parse('sc_markers.data.query');
//loop through all the markers from the database.
if (Array.isArray(markers)) {
markers.forEach(function(marker) {
if(marker.lat && marker.lng && marker.lat != 0){
var title = encodeURI(marker.title);
//This is what is going in the pop-up. It's very flexible, you can put cards/modals etc in here with whatever. This is just a simple example.
var template ='<div class="card"><div clas="card-header">' + marker.title + '</div><div class="card-body"><p class="card-text">' + marker.description + '</p></div></div>';
//Get the right icon
var thisIcon = window['icon'+marker.icon_id];
//Put it all together
var x = L.marker([marker.lat, marker.lng],{icon: thisIcon, title: marker.title, draggable: true}).bindPopup(template);
//Add it to the markers lager
x.addTo(markersLayer);
//Get the bounds for this marker
var lat_lng = [marker.lat, marker.lng];
//Extend the bounds to include this marker
bounds.extend(lat_lng);
}
});
//add all the markers to the map
markersLayer.addTo(map);
//fit the map to our markers
if(bounds.isValid()){
map.fitBounds(bounds);
}
}
}
//Keeps track of which popup is open
var currentPopup;
map.on("popupopen", function(evt){currentPopup = evt.popup});
</script>
<script src="bootstrap/4/js/popper.min.js"></script>
<script src="bootstrap/4/js/bootstrap.min.js"></script>
</body>
Hope that helps someone! Feel free to ask questions.