ROR学习笔记(44)——城市的级联

项目代码地址:https://coding.net/u/kamionayuki/p/tools/git 自己想写一个实现页面级联的功能,思路如下:
先获得城市的源数据,然后改成yaml的格式。一般来说,都是1个城市名称对应一个代码,代码可以是邮政编码,也可以是其它的,但肯定是一级城市与下级地区有关联。在服务器启动的时候,初始化一个常量,存放该数据。例如:

city.yaml

---
"北京(直辖市)": "101010000"
"北京": "101010100"
"海淀": "101010200"
"朝阳": "101010300"
"顺义": "101010400"
"怀柔": "101010500"
"通州": "101010600"
"昌平": "101010700"
"延庆": "101010800"
"丰台": "101010900"
"石景山": "101011000"
"大兴": "101011100"
"房山": "101011200"
"密云": "101011300"
"门头沟": "101011400"
"平谷": "101011500"
"八达岭": "101011600"
"佛爷顶": "101011700"
"汤河口": "101011800"
"密云上甸子": "101011900"
"斋堂": "101012000"
"霞云岭": "101012100"
.....

config/initializers,新增一个rb

require 'yaml'
require 'open-uri'   
require 'uri'
HAN_NAME = YAML.load(File.read(File.expand_path('../../../lib/genname.txt', __FILE__)))
CITY_DATA = YAML.load(File.read(File.expand_path('../../../lib/city.yaml', __FILE__)))

根据源数据把一级城市和二级城市的数据分开,并关联起来。

helpers/application_helper.rb

def get_provinces 
    provinces = CITY_DATA.select {|k,v| v[-4..-1] == "0000"}.to_a
    provinces.unshift(["--省份--", 0])
end

def get_cities(province_code) 
    cities = [["--城市--", 0]]
    return cities if province_code == 0
    if ["101010000", "101020000", "101030000", "101010000"].include?(province_code)    
      province_code[-3] = "1"    
      cities = CITY_DATA.select {|k,v| v == province_code}.to_a  
    else    
      cities = CITY_DATA.select {|k,v| v[3,2] == province_code[3,2] && v[-2..-1] == "01" }.to_a
    end
    cities.unshift(["--城市--", 0])
end
  
def get_area(province_code, city_code)  
    areas = [["--地区--", 0]]
    return cities if city_code == 0
    if ["101010000", "101020000", "101030000", "101010000"].include?(province_code)    
      areas =  CITY_DATA.select {|k,v| v[0..4] == city_code[0..4] && !["100", "000"].include?(v[-3..-1]) }.to_a  
    else    
      areas =  CITY_DATA.select {|k,v| v[0..-3] == city_code[0..-3] && !["00", "01"].include?(v[-2..-1])}.to_a
    end
    areas.unshift(["--地区--", 0])
end

在views中填写如下的代码:

<%= form_tag({controller: "tools", action: "get_weatherinfo"}, method: "get", remote: true) do %>  
  <div class="city-group">
    <%= select_tag :province, options_for_select(get_provinces,0), class: "province-select" %>
    <%= render('tools_form/cities', cities: [["--城市--", 0]]) %>
    <%= render('tools_form/areas', areas: [["--地区--", 0]]) %>
  </div>
  <%= button_to "查询天气" %>
<% end -%>

因为cities 和 areas是一个变值,会通过controller来获得,所以单独拿出来进行传值
tools_form/_cities.html.erb 和 tools_form/_areas.html.erb

<%= select_tag :city, options_for_select(cities, 0), class: "city-select" %>
# tools_form/_areas.html.erb
<%= select_tag :area, options_for_select(areas, 0), class: "area-select" %>

通过jquery来监听下拉菜单中值的变化,一旦有变化,则调用controller中的方法来获得对应的城市和地区
javascripts/tools.js。其中用$.post来传递一个url和一个值
如果province变化,则调用"/tools/get_cities_result",同时传递一个params[:province]的参数。
这样,get_cities_results就能使用该参数,从而获得对应的city,然后通过对应的js.erb文件来渲染当前页面

$('#province').change(function(){
    var province = $(this).children('option:selected').val();//这就是selected的值      
    $.post("/tools/get_cities_result",
       {
         province: province
       });
});

$('#city').change(function(){
    var province = $(this).prev().children('option:selected').val();
    var city = $(this).children('option:selected').val();//这就是selected的值   
    $.post("/tools/get_areas_result",
       {
         province: province,
         city: city
       });
});

controller中#因为要用到helper中的方法,所在以controllers/application_controller.rb中增加

include ApplicationHelper

tools_controller中,通过下面的方法来获得对应的城市和区域的值,然后用@cities和@areas来传递

def get_cities_result
    @cities = get_cities(params[:province])
end

def get_areas_result
    @areas = get_area(params[:province], params[:city])
end

因为是通过jquery.post方法来传递调用上面的方法的,所以对应的是js.erb文件,用来改变页面中城市和区域下拉框的值
tools/get_cities_result.js.erb

$('#city').html("<%=j render('tools_form/cities', cities: @cities) %>");
$('#area').html("<%=j render('tools_form/areas', areas: [["--地区--", 0]]) %>");
#tools/get_areas_result.js.erb
$('#area').html("<%=j render('tools_form/areas', areas: @areas) %>");

routes中

namespace :tools do
    get 'index'
    get 'rand_en_name'
    get 'rand_han_name'
    get 'rand_password'
    get 'timestamp_to_time'
    get 'time_to_timestamp'
    get 'han_number_transfer'
    get 'get_weatherinfo'
    get 'export' 
    post 'get_cities_result' 
    post 'get_areas_result' 
end

这样就实现了级联了。但不是纯前端的,网络差的时候,反应会慢一点。但这样就可以实现不仅仅是城市的级联了。类似于某某县某某高中某某年级某某班的级联都可以实现了。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 213,014评论 6 492
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,796评论 3 386
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 158,484评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,830评论 1 285
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,946评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,114评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,182评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,927评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,369评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,678评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,832评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,533评论 4 335
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,166评论 3 317
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,885评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,128评论 1 267
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,659评论 2 362
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,738评论 2 351

推荐阅读更多精彩内容