sapUI5/OpenUI5 Leafletjs custom control - leaflet

I am facing this issue with openUI5 and Leafletjs using a custom control from library.
Error:
"The renderer for class demo.map.SimpleMap is not defined or does not
define a render function! Rendering of __map0 will be skipped!"...
library.js
sap.ui.define([
'jquery.sap.global',
'sap/ui/core/library'],
function(jQuery){
"use strict";
sap.ui.getCore().initLibrary({
name: 'demo.map',
version: '1.0.0',
dependencies: ['sap.ui.core'],
types: [],
interfaces: [],
controls:[
'demo.map.SimpleMap'
],
elements:[]
});
return demo.map;
});
SimpleMap.js
sap.ui.define([
'jquery.sap.global',
'sap/ui/core/Control',
'./library'], function(jQuery, Control, library){
"use strict";
let SimpleMap = Control.extend('demo.map.SimpleMap',{
metadata:{
library: 'demo.map',
properties:{}
}
});
SimpleMap.prototype.drawMap = function(){
this.controlAspect = parseInt(450) / parseInt(350);
let map = L.map('map').setView([39.7166700,-8],8);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {attribution: '© OpenStreetMap contributors'}).addTo(map);
}
SimpleMap.prototype.onAfterRendering = function(){
this.drawMap();
}
return SimpleMap;
}, true);
SimpleMapRenderer.js
sap.ui.define(['jquery.sap.global'], function(jQuery){
"use strict";
let SimpleMapRenderer = {};
SimpleMapRenderer.renderer = function(oRm, oControl){
oRm.write('<div ');
oRm.writeControlData(oControl);
oRm.write('>');
oRm.write('</div>');
}
return SimpleMapRenderer;
});
Startpage.view.xml
<mvc:View controllerName="sap.ui.demo.fiori.controllers.Startpage" xmlns:mvc="sap.ui.core.mvc" xmlns="sap.m" xmlns:layout="sap.ui.layout">
<Page title="Fiori Tile Demo">
<layout:VerticalLayout class="sapUiResponsiveMargin">
<Title titleStyle="H2" text="Launchpad Menu" class="sapUiTinyMarginBegin"/>
<layout:HorizontalLayout allowWrapping="true" id="layout">
</layout:HorizontalLayout>
</layout:VerticalLayout>
</Page>
</mvc:View>
Startpage.controller.js
sap.ui.define(['sap/ui/demo/fiori/controllers/BaseController'], function(Controller){
"use strict";
return Controller.extend('sap.ui.demo.fiori.controller.Startpage',{
onInit:function(){
console.log('Startpage loaded');
let map = new demo.map.SimpleMap();
//console.log(map);
let oLay = this.getView().byId('layout');
oLay.addContent(map);
},
gotoUserList: function(){
this.getRouter().navTo('listUsers');
},
getRouter: function(){
return this.getOwnerComponent().getRouter();
}
});
});
Also, I have tried to add the map object directly from controller without custom control, but i got below error
'Map container not found' error from Leafletjs framework.
Hope someone please help me. I am pretty lost in how to render leaflet using openUI5.

Ok, this is how i could get it work:
SimpleMap.js
sap.ui.define(['jquery.sap.global','sap/ui/core/Control', './library'], function(jQuery, Control, library){
"use strict";
let SimpleMap = Control.extend('demo.map.SimpleMap',{
metadata:{
library: 'demo.map',
properties:{
"width":{type: 'sap.ui.core.CSSSize', defaultValue:'300px'},
"height":{type: 'sap.ui.core.CSSSize', defaultValue:'300px'}
}
}
});
SimpleMap.prototype._drawMap = function(){
this.controlAspect = parseInt(300) / parseInt(300);
/* using: L.map(this.$()).setView(...); << trown an error:
"Cannot read property 'baseVal' of undefined", which seems that is a jQuery object instead of a DOM element. Ref:
https://github.com/Leaflet/Leaflet/issues/2302
I couldn't how to get current DOM element.
*/
let map = L.map('map').setView([39.7166700,-8],8);
L.tileLayer('http://{s}.tile.osm.org/{z}/{x}/{y}.png', {attribution: '© OpenStreetMap contributors'}).addTo(map);
}
SimpleMap.prototype.onAfterRendering = function(){
this._drawMap();
}
return SimpleMap;
}, true);
SimpleMapRenderer.js
sap.ui.define(['jquery.sap.global'], function(jQuery){
"use strict";
let SimpleMapRenderer = {};
SimpleMapRenderer.render = function(oRm, oControl){
oRm.write('<div ');
oRm.write('id="map"'); // set it hardcoded
oRm.writeControlData(oControl);
oRm.addStyle('height',oControl.getHeight());
oRm.addStyle('width',oControl.getWidth());
oRm.writeStyles();
oRm.write('>');
oRm.write('</div>');
}
return SimpleMapRenderer;
}, true); // notice this: last version i did not export it...
Thanks for all your help.
PS.- Instead of using oRm.write('id="map"'); << and from control how to get dom element using this.$() ?
I have tried: this.$()[0] but nothing...

The error message pretty tell you precisely the problem: Your SimpleMapRenderer.js does not define a function called render. Instead you have called it renderer, which is what it would be called if you left it inside the SimpleMap.js. (Also, see edit below, the SimpleMapRenderer object needs to be exported, i.e. you need to add a true parameter to the define() call.)
The other problem ('Map container not found' error from Leafletjs framework.) will probably reappear once you fix the function name. That happens because your drawMap function directly references an element with id 'map'. OpenUI5 however will use the Control's id. You should change your call to
let map = L.map(this.getDomRef()).setView([39.7166700,-8],8);
That should create the map inside the div created by the ui5 renderer.
Edit: I've built the code in plnkr: http://plnkr.co/edit/BTDfwegfvO4iR4T3Mod0?p=preview
It shows I should have used getDomRef() instead of $(). Fixed above.
It also showed, you forgot to export the render class definition (and I didn't notice). After also adding a height to the div (and loading the css), it now properly draws a map.

Related

Defining Leaflet map as dynamic map id (Cannot read property '_container' of undefined)

I have 2 different divs which using by leaflet as map object. I want to define my map objects into a function such as
html
<div id="mymap"></div>
<div id="mymap2"></div>
javascript
var map;
function define_map(map_id) {
var osmUrl = 'http://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png',
osm = L.tileLayer(osmUrl, {
maxZoom: 7
}),
map = new L.Map(map_id, {
center: new L.LatLng(51.505, -0.04),
zoom: 7
}),
drawnItems = L.featureGroup().addTo(map);
});
define_map("mymap");
define_map("mymap2");
$(".btnmarker").on("click", function() {
console.log(map);
L.DomUtil.addClass(map._container, 'my_crosshair-cursor-enabled'); // ON THIS LINE GETTING ERROR CODE Cannot read property '_container' of undefined
selected_tool = $(this).attr("id");
});
There is no problem, my maps seems working good until accessing features of them from button click event (this button will add a marker class to a map which i clicked on it)
But i'm getting map is not defined error. map is a variable and defined on top line of page.
Thanks inadvance

onCloseDialog event not working in my Controller. What's wrong with my code?

I'm trying to learn SAPUI5 and following the walkthrough in SAPUI5 documentation. I'm currently in Step 17: Fragment Callbacks. I am not able to make the onCloseDialog event work. The code I double and triple checked and I could not find anything wrong. There is also no error in Chrome's console. Any insights?
Link to the guide I'm following:
https://sapui5.hana.ondemand.com/#/topic/354f98ed2b514ba9960556333428d35e
My code for:
HelloDialog.fragment.xml
<core:FragmentDefinition xmlns="sap.m" xmlns:core="sap.ui.core">
<Dialog id="helloDialog" title="Hello {/recipient/name}">
<content>
<core:Icon src="sap-icon://hello-world" size="8rem" class="sapUiMediumMargin"/>
</content>
<beginButton>
<Button text="{i18n>dialogCloseButtonText}" press="onCloseDialog"/>
</beginButton>
</Dialog>
My code for:
HelloPanel.controller.js
sap.ui.define([
"sap/ui/core/mvc/Controller",
"sap/m/MessageToast"
], function(Controller, MessageToast) {
"use strict";
return Controller.extend("sap.ui.demo.wt.controller.HelloPanel", {
onShowHello: function() {
// read msg from i18n model
var oBundle = this.getView().getModel("i18n").getResourceBundle();
var sRecipient = this.getView().getModel().getProperty("/recipient/name");
var sMsg = oBundle.getText("helloMsg", [sRecipient]);
// show message
MessageToast.show(sMsg);
},
onOpenDialog: function() {
var oView = this.getView();
var oDialog = oView.byId("helloDialog");
// create dialog lazily
if (!oDialog) {
// create dialog via fragment factory
oDialog = sap.ui.xmlfragment(oView.getId(), "sap.ui.demo.wt.view.HelloDialog");
oView.addDependent(oDialog);
}
oDialog.open();
},
onCloseDialog: function() {
this.getView().byId("helloDialog").close();
}
});
});
You missed to pass the controller reference when creating the dialog from the fragment.
In case of the Walkthrough step, it's the same controller object as the dialog caller, so this should be passed:
sap.ui.xmlfragment(oView.getId(), "sap.ui.demo.wt.view.HelloDialog", this);⚠️
API reference: sap.ui.xmlfragment⚠️
⚠️ sap.ui.*fragment is deprecated!
Instead, use one of the APIs mentioned in https://stackoverflow.com/a/64541325/5846045.
Documentation topic: Instantiation of Fragments

SAPUI5 - How do I implement RichTextEditor?

Not Sure if the Documenatation is out of Date, but the standard code for creating a new richtext editor returns
Cannot read property 'RichTextEditor' of undefined
It looks like this is because there is no sap.ui.richtexteditor in the list of included resources.
var oRichTextEditor1 = new sap.ui.richtexteditor.RichTextEditor("myRTE1", {
width:"100%",
height:"300px",
showGroupClipboard:true,
showGroupStructure:true,
showGroupFont:true,
showGroupInsert:true,
showGroupLink:true,
showGroupUndo:true,
tooltip:"My RTE Tooltip"
});
What are my other options for a RichText/WYSIWYG editor in SAPUI5 ?
You should use the sap.ui.define syntax to require the RichTextEditor control in your controller. As the control library is not included in the resources, it would not be readily available.
sap.ui.define([
"com/sap/app/controller/BaseController",
.
.
.
"sap/ui/richtexteditor/RichTextEditor"
], function (BaseController, ........, RichTextEditor) {
onAfterRendering: function () {
var oRichTextEditor1 = new RichTextEditor("myRTE1", {
width:"100%",
height:"300px",
showGroupClipboard:true,
showGroupStructure:true,
showGroupFont:true,
showGroupInsert:true,
showGroupLink:true,
showGroupUndo:true,
tooltip:"My RTE Tooltip"
});
}
});

Mapbox Filter Markers loaded via json

I am looking for solution to add filter (not checkbox) to my site. I have this code loading blank map from Mapbox and added Markers from JSON file. I was trying to add setFilter function, but probably I am using it wrong. I would like to filter items by category property from my JSON file.
<script>
L.mapbox.accessToken = '*************';
var baseLayer = L.mapbox.tileLayer('test****');
var markers = L.markerClusterGroup();
// CALL THE GEOJSON HERE
jQuery.getJSON("locations.geojson", function(data) {
var geojson = L.geoJson(data, {
onEachFeature: function (feature, layer) {
// USE A CUSTOM MARKER
layer.setIcon(L.mapbox.marker.icon({'marker-symbol': 'circle-stroked', 'marker-color': '004E90'}));
// ADD A POPUP
layer.bindPopup("<h1>" + feature.properties.title + "</h1><p>" + feature.properties.description + "</p><p><a href=' + feature.properties.website + '>" + feature.properties.website + "</a></p>");
layer.on('mouseover', function (e) {
this.openPopup();
});
layer.on('mouseout', function (e) {
this.closePopup();
});
}
});
markers.addLayer(geojson);
// CONSTRUCT THE MAP
var map = L.map('map', {
searchControl: {layer: markers},
zoom: 6,
center: [51.505, -0.09],
maxZoom: 13
})
.setView([62.965, 19.929], 5)
.fitBounds(markers.getBounds());
baseLayer.addTo(map);
markers.addTo(map);
L.control.fullscreen().addTo(map);
});
</script>
Could you please help me add filter buttons (something like here: https://www.mapbox.com/mapbox.js/example/v1.0.0/filtering-markers)
PS: I think I tried all examples from Mapbox website, yet seems my skills are very limited here.
Thank you
I was trying to add setFilter function, but probably I am using it wrong. I would like to filter items by category property from my JSON file.
This code example is using L.geoJson to load the markers into your map. Like the Mapbox example, you'll need to use L.mapbox.featureLayer instead, since it includes the setFilter function and L.geoJson does not.
tmcw's answer is correct, L.mapbox.featureLayer is confusing
this tutorial helped me!
https://www.mapbox.com/mapbox.js/example/v1.0.0/custom-marker-tooltip/

Cant open popup programmatically

I have a map on which im loading the markers with geoJSON.
When the map loads i run a function buildVisibleSys which is responsible to build a list of currently visible systems on the map.
That function looks like this:
buildVisibleSys = function() {
var bounds, visibleSys;
visibleSys = [];
bounds = map.getBounds();
return systemLocations.eachLayer(function(marker) {
var link;
link = onScreenEl.appendChild(document.createElement('a'));
link.href = '#';
link.id = "marker" + marker._leaflet_id;
link.innerHTML = marker.options.title;
link.onclick = function() {
marker.openPopup();
map.panTo(marker.getLatLng());
};
});
};
map.on('load', buildVisibleSys);
In this function, for each layer im getting some data and building a html block with the names of each marker. Each of those names, associated to the link var, have a onclick event attached that will center the map on the correspondent marker. This all works except for the marker.openPopup() call i also have on that onclick event.
Any idea of what am I missing here?
I've also made a demo of the code available here:
http://jsfiddle.net/lmartins/z8wBW/
UPDATE:
Even more confusing to me is that with mouseover the same method works without a problem, that is, in the function above the following code do open the popup:
link.onmouseover = function(ev) {
marker.openPopup();
marker._icon.classList.add('is-active');
};
Change your link handler to
link.onclick = function(e) {
marker.openPopup();
map.panTo(marker.getLatLng());
e.stopPropagation();
e.preventDefault();
};
The click of the link to open the popup is bubbling down to the map and closing the popup right after it's opened.