Sencha Touch - Add Markers to Map after Maprender - google-maps

I want to load markers to my map, in sencha touch, after I load some json data from ajax request. The thing is I don't know how to achieve this after the maprender event is fired.
I've got this:
my map view:
app.views.MapTab = Ext.extend(Ext.Panel, {
iconCls: 'map',
id: 'map',
items: [{
xtype: 'map',
id: 'mapa',
mapOptions : {
center : new google.maps.LatLng(50.077721, 14.448585),
zoom : 12,
mapTypeId : google.maps.MapTypeId.ROADMAP,
navigationControl: true,
navigationControlOptions: {
style: google.maps.NavigationControlStyle.DEFAULT
}
},
listeners : {
'maprender' : function(comp, map){
Ext.dispatch({
controller: app.controllers.map,
action: 'map_rendered',
map: map
});
}
}
}],
initComponent: function() {
app.views.MapTab.superclass.initComponent.apply(this, arguments);
}
});
store to load json:
app.stores.results = new Ext.data.Store({
model: "app.models.Results",
proxy: {
type: 'ajax',
url: 'http://app.cz/json_list2.php?a=l&zp=1&u=vinohrady-praha&c0=500000&c1=6000000&p0=10&p1=120&cm20=1000&cm21=120000&pg=0&s=Datumu&t=byt&age=30&pod=0&lat=50.075401&lng=14.458344&pp=prodej&tp0=0&tp1=12',
reader: {
type: 'json',
root: 'markers'
}
},
listeners: {
'load': function (t, r, s) {
Ext.dispatch({
controller: app.controllers.map,
action: 'loaded',
records: r
});
}
}
});
controller
app.controllers.map = new Ext.Controller({
loaded: function(options) {
for(var i = 0; i < options.records.length; i++){
var marker = new google.maps.Marker({
position: new google.maps.LatLng(options.records[i].get('lat'), options.records[i].get('lng')),
map: app.views.mapTab.getComponent('mapa')
});
}
// need to rerender/refresh the map here
},
map_rendered: function(options) {
console.log("map rendered");
}
});

Your code should work but you are attaching the markers to the Sencha Touch Map component rather than the underlying Google Maps map, which can be accessed with the 'map' property.
...
var marker = new google.maps.Marker({
position: new google.maps.LatLng(options.records[i].get('lat'), options.records[i].get('lng')),
**map: app.views.mapTab.getComponent('mapa').map**
});
...
The map shouldn't need manually re-rendered and should just add them in when you bind them with the map config.

Related

Adding geometries to data layer - how to set feature styles during add?

I'm building a school layer. For each school, I will assign a different icon depending on its properties.
This is my current solution. I first insert all the schools into a data layer, and then run a forEach function to change each point's icon. This is not optimal, because I am adding the schools, then immediately editing the schools.
// Current solution. It is WORKING but it is not optimal
schools = (a list of google.maps.Data.Point objects)
for (school in schools) {
schoolLayer.add({
geometry: school,
});
}
schoolLayer.forEach(function(feature) {
schoolLayer.overrideStyle(feature, {
if (some condition) {
icon: ...
} else {
icon: ...
}
}
}
The optimal solution would be to add styles to the school while it is added, so that no editing is required afterwards. Something like this:
// The solution I am trying to achieve. The `StyleOptions` property is made up to represent what I am trying to achieve. I want to add styles to the school as it is being inserted into the data layer
for (school in schools) {
schoolLayer.add({
geometry: school,
StyleOptions: {
if (some condition) {
icon: ...
} else {
icon: ...
}
}
});
}
The above code does not work. Is there something I'm missing from the documentation that allows me to achieve that?
I would suggest creating a list of google.maps.Data.Feature objects instead of the google.maps.Data.Point objects. Data.Feature can include geometry that is an instance of google.maps.Data.Point in your case, id that can be string or number and properties where you can put name-value pairs.
https://developers.google.com/maps/documentation/javascript/reference/3/data#Data.Feature
The presence of properties in a feature makes a trick. You can apply a styling function for your data layer that reads property of the feature (icon in your case) and returns corresponding style. The styling function will be applied when you add a feature to the data layer.
Have a look at the following code sample, the schoolLayer.setStyle() is the most relevant part
var map;
function initMap() {
var schools = [
new google.maps.Data.Feature({
geometry: new google.maps.Data.Point({lat: 41.384301, lng: 2.173792}),
id: 1,
properties: {
"icon": "http://maps.google.com/mapfiles/kml/paddle/blu-blank.png"
}
}),
new google.maps.Data.Feature({
geometry: new google.maps.Data.Point({lat: 41.384897, lng: 2.176656}),
id: 2,
properties: {
"icon": "http://maps.google.com/mapfiles/kml/paddle/pink-blank.png"
}
}),
new google.maps.Data.Feature({
geometry: new google.maps.Data.Point({lat: 41.386756, lng: 2.175268}),
id: 3,
properties: {
"icon": "https://maps.gstatic.com/mapfiles/place_api/icons/geocode-71.png"
}
})
];
map = new google.maps.Map(document.getElementById('map'), {
zoom: 17,
center: {lat: 41.385064, lng: 2.173403}
});
var schoolLayer = map.data;
schoolLayer.setStyle(function(feature){
return {
icon: feature.getProperty("icon"),
title: "" + feature.getId()
};
});
for (school of schools) {
schoolLayer.add(school);
}
}
#map {
height: 100%;
}
html, body {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<script async defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyDztlrk_3CnzGHo7CFvLFqE_2bUKEq1JEU&callback=initMap">
You can also find this example on jsfiddle: https://jsfiddle.net/xomena/tLsjkowp/
I hope this helps!
#xonema - Great answer.
Just adding that I set the properties locally in this manner:
new google.maps.Data.Feature({
geometry: new google.maps.Data.Point(gaugeLatLng),
properties: {
title: gaugeDetail.gaugeId,
icon: {
path: google.maps.SymbolPath.CIRCLE,
scale: 6,
},
}
})

Meteor reactive maps don't work as should

I am using two brilliant packages named dburles:google-maps and mdg:geolocation. What I nee is to add a marker and change map's zoom automatically when I get user's geolocation data (after he allows it to share).
Inside Template.onCreated I have the following code:
Template.dealersMap.onCreated(function() {
Tracker.autorun(() => {
this.latLng = new ReactiveVar(Geolocation.latLng());
})
});
Then in onRendered I do the following:
Template.dealersMap.onRendered(function() {
navigator.geolocation.getCurrentPosition((position) => {
GoogleMaps.ready('exampleMap', (map) => {
let marker;
if(!this.latLng.get())
console.log('Didn\'t get the location..');
if(!marker) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(
this.latLng.get().lat,
this.latLng.get().lng
),
map: map.instance
});
} else {
marker.setPosition(this.latLng.get());
}
map.instance.setCenter(marker.getPosition());
map.instance.setZoom(11);
}, () => {
console.log('deny');
});
})
});
As result after user allows me to get his geodata nothing happens. But if user changes at least one step map zoom — everything works.
The question is — how to make this code work without letting user change map zoom?
I just removed navigator.geolocation.getCurrentPosition and now everything works fine. Here is the successful code:
Template.dealersMap.onCreated(function() {
this.latLng = new ReactiveVar();
Tracker.autorun(() => {
this.latLng.set(Geolocation.latLng());
})
});
Template.dealersMap.onRendered(function() {
this.autorun(() => {
GoogleMaps.ready('exampleMap', (map) => {
console.log('map is ready');
let marker;
if(!this.latLng.get()) {
console.log('Didn\'t get the location..');
} else {
if(!marker) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(
this.latLng.get()
.lat,
this.latLng.get()
.lng
),
map: map.instance
});
} else {
marker.setPosition(this.latLng.get());
}
}
map.instance.setCenter(marker.getPosition());
map.instance.setZoom(11);
})
})
});
You can use Tracker to rerun the once the dta is changed like, once uses share his/her location, the marker is triggered. Here is the example code:
Template.dealersMap.onRendered(function() {
var self=this;
navigator.geolocation.getCurrentPosition((position) => {
GoogleMaps.ready('exampleMap', (map) => {
self.autorun(function() { //tracker function
let marker;
if(!this.latLng.get())
console.log('Didn\'t get the location..');
if(!marker) {
marker = new google.maps.Marker({
position: new google.maps.LatLng(
this.latLng.get().lat,
this.latLng.get().lng
),
map: map.instance
});
} else {
marker.setPosition(this.latLng.get());
}
map.instance.setCenter(marker.getPosition());
map.instance.setZoom(11);
}, () => {
console.log('deny');
}
});
})
});

Plotting Multiple JSON data in flot chart using angularjs

I am using angularjs and JSON to plot flot chart, i am using multiple encoded JSON to draw the line of the Flot line chart, doing so the bar comes out empty.
Not quite sure what is wrong.
HTML
<flot id="placeholder" dataset="dataset" options="options" height="250px"></flot>
JS
.factory("services", ['$http', function($http) {
var serviceBase = 'http://maricoih.e21designs.com/services/'
var obj = {};
obj.getope = function(){
return $http.get(serviceBase + 'productionhourlys');
}
obj.getcopra = function(){
return $http.get(serviceBase + 'productionhourlyscopra');
}
return obj;
}])
.controller('LineChartCtrl', function ($scope,$http,services) {
$scope.dataset = [{
data: obj.getope(),
label: 'OPE',
points: {
show: true,
radius: 6
}
}, {
data: obj.getcopra(),
label: 'OEE',
points: {
show: true,
radius: 6
}
}];
})

Current location in sencha touch

I am using the following code to display my current location on Sencha Touch 2. Its showing the correct latitude in console.log() but not showing the map. Please help.
Ext.define('restApp.view.GreetingView', {
extend: 'Ext.Map',
alias: 'widget.mymap',
config: {
fullscreen: true,
//tpl: '<p>The ID is {uuid}</p><p>The content is {display}</p>',
layout: {
type: 'fit'
}
},
initialize:function(){
Ext.Viewport.add({
xtype: 'map',
id:'geomap',
itemId:'ma'
});
var geo = Ext.create('Ext.util.Geolocation', {
autoUpdate: true,
frequency: '10000',
listeners: {
locationupdate: function (geo) {
var center = new google.maps.LatLng(geo.getLatitude(), geo.getLongitude());
Ext.getCmp('geomap').setData(center);
//restApp.view.GreetingView.getComponent('ma').update(center);
var marker = new google.maps.Marker({
position: center,
map: Ext.getCmp('geomap').map
});
console.log('New latitude: '+ geo.getLatitude());
},
locationerror: function (geo, bTimeout, bPermissionDenied, bLocationUnavailable, message) {
if (bTimeout) {
alert('Timeout occurred.');
}
else {
alert('Error occurred.');
}
}
}
});
}
});
OLD ANSWER
Comparing it to a snippet I use for the same purpose (shown below), I realised the issue is a simple one. "center" is a reserved word. Try using a different variable name.
PART OF EDIT: removal of code snippets.
NEW ANSWER
I looked around and noticed your "project" is but a piecemeal collection of demo code.
Here's a complete code solution, with all excess pieces removed for simplicity, as well as over use of variables, also expanded to a longwinded format to be obvious.
/*
The application, including a simple launcher.
*/
Ext.application({
requires : ['Ext.device.Geolocation'],
views : ['MainView'],
controllers : ['Maps'],
name : 'Geo',
launch: function() {
Ext.create('Geo.view.MainView', {fullscreen: true});
}
});
/*
The View to display the map, as well as how to include the navigation bar
and include a "you are here" button.
*/
Ext.define('Geo.view.MainView', {
extend: 'Ext.navigation.View',
alias: 'widget.mainview',
requires: [
'Ext.Panel',
'Ext.Map',
'Ext.navigation.Bar',
'Ext.Button'
],
config: {
items: [
{
xtype : 'panel',
title : 'Map',
itemId : 'mapPanel',
items : [
{
xtype: 'map',
height: '100%',
itemId: 'map'
}
]
}
],
navigationBar: {
docked: 'top',
items: [
{
xtype: 'button',
itemId: 'youAreHereButton',
text: 'You Are Here'
}
]
}
}
});
/*
The Controller with functionality for the "you are here" button tap
*/
Ext.define('Geo.controller.Maps', {
extend: 'Ext.app.Controller',
config: {
refs: {
mapView: {
selector: 'mainview #map',
xtype: 'Ext.Map'
},
mainView: {
selector: 'mainview',
xtype: 'Ext.navigation.View'
}
},
control: {
"mainview #youAreHereButton": {
tap: 'onYouAreHereTap'
}
}
},
onYouAreHereTap: function(button, e, eOpts) {
// set 'mapView' as the parent view displaying the map
var mapView = this.getMapView();
// control measure for old browsers or denied permission for location detection.
if (Ext.feature.has.Geolocation) {
/*
Ext.device.Geolocation uses native (phone) Geolocation capabilities if available,
and falls back to Ext.util.Geolocation if only browser support detected.
*/
Ext.device.Geolocation.getCurrentPosition({
allowHighAccuracy : true,
maximumAge : 0,
timeout : 20000,
success : function(position) {
var latitude = position.coords.latitude,
longitude = position.coords.longitude,
location = new google.maps.LatLng(latitude, longitude),
marker = new google.maps.Marker({
position : location,
map : mapView.getMap(),
animation : google.maps.Animation.DROP
});
mapView.setMapOptions({ // Move to the center
center: location
});
},
failure: function() {
console.log('something went wrong!');
}
});
}
}
});
Yes, I could have simplified it further down to a single view, containing also the controller's handler for the "you are here" tap. I have chosen to present it this way to assist you with understanding the MVC pattern and how it applies in Sencha Touch.
For this to work, it'll require the Sencha Touch library, as well as this following line:
<script src="http://maps.google.com/maps/api/js?sensor=true"></script>
This is the script which includes Google Maps in your page and is essential for displaying.
Learn more:
https://www.sencha.com/learn/hello-world/ - getting started
http://docs.sencha.com/touch/2.3.1/#!/guide - complete documentation for how to do anything in Sencha Touch, starting with the Guides page.

Sencha Touch not firing beforeshow event listener

Im new to sencha touch and going through the obligatory hair pulling and head2desk pounding.
Im trying to display a List but Im having a problem.
Im using a beforeshow event to load my json store before the list is displayed. But it's not firing the event. If any can help it is MOST appreciated.
My code is as follows: *note- this code is AS/400 centric so the /%...%/ is for that
function doList() {
var List1 = new Ext.List ({
id : List1,
renderTo : 'panel',
fullscreen: true,
showAnimation: {
type: 'slide',
duration: 250
},
cls: 'demo-list',
width: Ext.is.Phone ? undefined : 300,
height: 500,
store: ListStore,
itemTpl: '<strong>{SCEQPT}</strong>',
grouped: true,
indexBar: true,
onItemDisclosure: function(record, btn, index) {
doPopUp(record);
},
listeners: {
'beforeshow': function () {
alert('beforeshow');
var StoreList = Ext.StoreMgr.get('ListStore'
StoreList.load({
params: {
screfr: Ext.getCmp('SCREFR').getValue(),
scptyp: scptyp,
user : '/%SCUSER%/'
}
});
}
}
});
}
beforeshow listener is triggered only when you are displaying an item with show() method.
Try using the listeners
'render','beforerender' and 'afterrender'. instead.