Google Rails 的地图 - 用 AJAX 更新标记
Google Maps for Rails - update markers with AJAX
我正在开发一个网络应用程序,我在 Rails 上使用 Ruby。我们的索引由地图和搜索字段组成。您可以搜索位置,地图会更新其标记。
我想使用 Ajax 来避免刷新页面。所以我在表单中添加了 remote: true
,在控制器中添加了一个 respond_to
和一个新的 search.js.erb.
我的 search.js.erb
呈现了一个部分 _googlemap.erb
,其中包含用于初始化地图。
这是我的问题。由于地图已经存在,就像我想两次创建同一个对象一样,这当然行不通而且很糟糕。我只想用新标记更新地图中的标记。但是我找不到办法。
我看到以前版本的 Gmaps4rails 集成了一种方法(Gmaps.map.replaceMarkers(your_markers_json_array);
),但现在似乎不起作用。当我使用它时,我得到了这个错误:“TypeError: Gmaps.map is undefined
”。我尝试使用“handler.replaceMarkers();
”,但这次我使用的是“TypeError: handler.replaceMarkers is not a function
”。
我是 Javascript 和 Rails 的新手,但我想提高自己的知识,我确实需要继续学习此 Web 应用程序的其余部分。我一直在网上到处寻找解决方案,但没有成功。
拜托,有人能告诉我我该怎么做以及我做错了什么吗?
非常感谢,
席琳
zones_controller.rb
def search
respond_to do |format|
format.html.none do
search_params = params[:zone][:search]
coordinates = Geocoder.coordinates(search_params).join(",")
@zones = Zone.search(
"", { "aroundLatLng" => coordinates,
"aroundRadius" => 500000 #Searches around 500 km
})
if coordinates.nil?
@zones = Zone.search(params[:search])
elsif @zones.empty?
@zones = Zone.all
flash[:error] = "No zone could be found. Please try again."
end
build_map(@zones)
end
format.js
end
end
def build_map(array)
@hash = Gmaps4rails.build_markers(array) do |zone, marker|
marker.lat zone.latitude
marker.lng zone.longitude
marker.json({ title: zone.description, id: zone.id })
marker.infowindow render_to_string(:partial => "/zones/map_box", locals: { zone: zone })
end
end
search.html.erb
<div id="map" style='width: 100%; height: 700px;'>
</div>
<!-- Beginning Google maps -->
<script type="text/javascript" id="map_script">
$(document).ready(function() {
<%= render 'googlemap', hash: @hash %>
}); // Document ready
</script>
_googlemap.erb
handler = Gmaps.build('Google');
handler.buildMap({ provider: {
disableDefaultUI: true,
mapTypeId: google.maps.MapTypeId.TERRAIN
}, internal: {id: 'map'}
}, function(){
markers_json = <%= raw hash.to_json %>;
markers = _.map(markers_json, function(marker_json){
marker = handler.addMarker(marker_json);
handler.getMap().setZoom(4);
_.extend(marker, marker_json);
marker.infowindow = new google.maps.InfoWindow({
content: marker.infowindow
});
return marker;
});
handler.bounds.extendWith(markers);
handler.fitMapToBounds();
});
search.js.erb
$('#map_script').replaceWith("<%= render 'googlemap', hash: @hash %>");
我尝试了同样的事情,但不是更新 marker
你应该在 partial/placeholder
中包含地图然后更新它 ...
例如,这是显示地图的视图...我将用最新的地图和标记更新此 view/placeholder
<div id="map_users_index">
<div id="map" class="map" style="height:relative;">
</div>
在users_controller.rb
##take index action or any other action
def index
##do your stuff and get more users
respond_to do |format|
format.html
format.js
end
end
在index.js.erb
##update the placeholder/partial with new map with new markers
$("#map_users_index").html("<%= escape_javascript(render(:partial => 'index')) %>");
我有自己的工作代码...HERE
你为什么不用新标记更新地图?意思是,不是在每次搜索后重新渲染整个地图,而是通过删除所有标记并添加新标记来更新现有地图上的标记。
我还没有验证这个方法,但我想它应该有效并且更有效:
创建一个 app/assets/javascript/map.js
文件。您可以在那里存储与地图相关的功能。创建一个函数来更新此文件中地图的标记:
map.js
(function() {
/* __markers will hold a reference to all markers currently shown
on the map, as GMaps4Rails won't do it for you.
This won't pollute the global window object because we're nested
in a "self-executed" anonymous function */
var __markers;
function updateMarkers(map, markersData)
{
// Remove current markers
map.removeMarkers(__markers);
// Add each marker to the map according to received data
__markers = _.map(markersData, function(markerJSON) {
marker = map.addMarker(markerJSON);
map.getMap().setZoom(4); // Not sure this should be in this iterator!
_.extend(marker, markerJSON);
marker.infowindow = new google.maps.InfoWindow({
content: marker.infowindow
});
return marker;
});
map.bounds.extendWith(__markers);
map.fitMapToBounds();
};
// "Publish" our method on window. You should probably have your own namespace
window.updateMarkers = updateMarkers;
})();
此函数可用于初始化您的地图并对其进行更新。由于您不会(如果我的回答令您满意)渲染地图两次,您可以删除 _google_map.erb
并将其内容放回 search.html.erb
,但使用我们刚刚创建的函数:
search.html.erb
<div id="map" style='width: 100%; height: 700px;'>
</div>
<!-- Beginning Google maps -->
<script type="text/javascript" id="map_script">
$(document).ready(function() {
mapHandler = Gmaps.build('Google');
mapHandler.buildMap({ provider: {
disableDefaultUI: true,
mapTypeId: google.maps.MapTypeId.TERRAIN
}, internal: {id: 'map'}
}, function(){
var markersData = <%= raw @hash.to_json %>;
updateMarkers(mapHandler, markersData);
});
}); // Document ready
</script>
请在声明变量时不要忘记var关键字,否则它们最终会成为全局变量,这很糟糕^^
请注意,我故意将 mapHandler
保留为全局变量:稍后当有人使用搜索时,您将需要访问您的处理程序以更新标记。这可能不是一件理想的事情,但这个问题与重构代码无关,所以让我们保持这种方式。
所以现在我的解决方案为您带来了一张地图,该地图在页面加载时使用给定的标记进行初始化。换句话说,什么都没有改变!
不过,您现在可以重复使用此 updateMarkers
函数来更改地图上显示的标记。这就是你 search.js.erb
脚本应该做的:
search.js.erb
(function() {
var markersData = <%= raw @hash.to_json %>;
updateMarkers(mapHandler, markersData);
})();
就是这样!希望它能带您进入项目的下一步:)
我正在开发一个网络应用程序,我在 Rails 上使用 Ruby。我们的索引由地图和搜索字段组成。您可以搜索位置,地图会更新其标记。
我想使用 Ajax 来避免刷新页面。所以我在表单中添加了 remote: true
,在控制器中添加了一个 respond_to
和一个新的 search.js.erb.
我的 search.js.erb
呈现了一个部分 _googlemap.erb
,其中包含用于初始化地图。
这是我的问题。由于地图已经存在,就像我想两次创建同一个对象一样,这当然行不通而且很糟糕。我只想用新标记更新地图中的标记。但是我找不到办法。
我看到以前版本的 Gmaps4rails 集成了一种方法(Gmaps.map.replaceMarkers(your_markers_json_array);
),但现在似乎不起作用。当我使用它时,我得到了这个错误:“TypeError: Gmaps.map is undefined
”。我尝试使用“handler.replaceMarkers();
”,但这次我使用的是“TypeError: handler.replaceMarkers is not a function
”。
我是 Javascript 和 Rails 的新手,但我想提高自己的知识,我确实需要继续学习此 Web 应用程序的其余部分。我一直在网上到处寻找解决方案,但没有成功。
拜托,有人能告诉我我该怎么做以及我做错了什么吗?
非常感谢,
席琳
zones_controller.rb
def search
respond_to do |format|
format.html.none do
search_params = params[:zone][:search]
coordinates = Geocoder.coordinates(search_params).join(",")
@zones = Zone.search(
"", { "aroundLatLng" => coordinates,
"aroundRadius" => 500000 #Searches around 500 km
})
if coordinates.nil?
@zones = Zone.search(params[:search])
elsif @zones.empty?
@zones = Zone.all
flash[:error] = "No zone could be found. Please try again."
end
build_map(@zones)
end
format.js
end
end
def build_map(array)
@hash = Gmaps4rails.build_markers(array) do |zone, marker|
marker.lat zone.latitude
marker.lng zone.longitude
marker.json({ title: zone.description, id: zone.id })
marker.infowindow render_to_string(:partial => "/zones/map_box", locals: { zone: zone })
end
end
search.html.erb
<div id="map" style='width: 100%; height: 700px;'>
</div>
<!-- Beginning Google maps -->
<script type="text/javascript" id="map_script">
$(document).ready(function() {
<%= render 'googlemap', hash: @hash %>
}); // Document ready
</script>
_googlemap.erb
handler = Gmaps.build('Google');
handler.buildMap({ provider: {
disableDefaultUI: true,
mapTypeId: google.maps.MapTypeId.TERRAIN
}, internal: {id: 'map'}
}, function(){
markers_json = <%= raw hash.to_json %>;
markers = _.map(markers_json, function(marker_json){
marker = handler.addMarker(marker_json);
handler.getMap().setZoom(4);
_.extend(marker, marker_json);
marker.infowindow = new google.maps.InfoWindow({
content: marker.infowindow
});
return marker;
});
handler.bounds.extendWith(markers);
handler.fitMapToBounds();
});
search.js.erb
$('#map_script').replaceWith("<%= render 'googlemap', hash: @hash %>");
我尝试了同样的事情,但不是更新 marker
你应该在 partial/placeholder
中包含地图然后更新它 ...
例如,这是显示地图的视图...我将用最新的地图和标记更新此 view/placeholder
<div id="map_users_index">
<div id="map" class="map" style="height:relative;">
</div>
在users_controller.rb
##take index action or any other action
def index
##do your stuff and get more users
respond_to do |format|
format.html
format.js
end
end
在index.js.erb
##update the placeholder/partial with new map with new markers
$("#map_users_index").html("<%= escape_javascript(render(:partial => 'index')) %>");
我有自己的工作代码...HERE
你为什么不用新标记更新地图?意思是,不是在每次搜索后重新渲染整个地图,而是通过删除所有标记并添加新标记来更新现有地图上的标记。
我还没有验证这个方法,但我想它应该有效并且更有效:
创建一个 app/assets/javascript/map.js
文件。您可以在那里存储与地图相关的功能。创建一个函数来更新此文件中地图的标记:
map.js
(function() {
/* __markers will hold a reference to all markers currently shown
on the map, as GMaps4Rails won't do it for you.
This won't pollute the global window object because we're nested
in a "self-executed" anonymous function */
var __markers;
function updateMarkers(map, markersData)
{
// Remove current markers
map.removeMarkers(__markers);
// Add each marker to the map according to received data
__markers = _.map(markersData, function(markerJSON) {
marker = map.addMarker(markerJSON);
map.getMap().setZoom(4); // Not sure this should be in this iterator!
_.extend(marker, markerJSON);
marker.infowindow = new google.maps.InfoWindow({
content: marker.infowindow
});
return marker;
});
map.bounds.extendWith(__markers);
map.fitMapToBounds();
};
// "Publish" our method on window. You should probably have your own namespace
window.updateMarkers = updateMarkers;
})();
此函数可用于初始化您的地图并对其进行更新。由于您不会(如果我的回答令您满意)渲染地图两次,您可以删除 _google_map.erb
并将其内容放回 search.html.erb
,但使用我们刚刚创建的函数:
search.html.erb
<div id="map" style='width: 100%; height: 700px;'>
</div>
<!-- Beginning Google maps -->
<script type="text/javascript" id="map_script">
$(document).ready(function() {
mapHandler = Gmaps.build('Google');
mapHandler.buildMap({ provider: {
disableDefaultUI: true,
mapTypeId: google.maps.MapTypeId.TERRAIN
}, internal: {id: 'map'}
}, function(){
var markersData = <%= raw @hash.to_json %>;
updateMarkers(mapHandler, markersData);
});
}); // Document ready
</script>
请在声明变量时不要忘记var关键字,否则它们最终会成为全局变量,这很糟糕^^
请注意,我故意将 mapHandler
保留为全局变量:稍后当有人使用搜索时,您将需要访问您的处理程序以更新标记。这可能不是一件理想的事情,但这个问题与重构代码无关,所以让我们保持这种方式。
所以现在我的解决方案为您带来了一张地图,该地图在页面加载时使用给定的标记进行初始化。换句话说,什么都没有改变!
不过,您现在可以重复使用此 updateMarkers
函数来更改地图上显示的标记。这就是你 search.js.erb
脚本应该做的:
search.js.erb
(function() {
var markersData = <%= raw @hash.to_json %>;
updateMarkers(mapHandler, markersData);
})();
就是这样!希望它能带您进入项目的下一步:)