2

私はindex.html.erbDataTablesJavaScriptを使用して、表形式でレンダリングするためのindex.html.erbに渡され、別のカスタム開発されたクラスから私のプロダクトのインデックスを取得していますに渡されますページ。このコードは、server sidepaginationsortingfilteringをやって、これまでのところ非常によくウォーキングされていますが、今私はそれが@hashとして渡される前ProductsControllerでそれを処理したいDataTablesで使用JSONから@products変数を取得したいです最終的に別のJavaScript@markers@productsGoogle Mapに表示します。ここでRailsは、別のJavaスクリプト

は私のコードです:

私は、コントローラ内でユーザーがページのインデックスページ間を移動ような方法を @productsを取得できますか

products_controller.rb

... 
    def index 
    respond_to do |format| 
     format.html 
     format.json { render json: ProductsDatatable.new(view_context) } 
    end 
    end 
... 

index.html.erb

<div class="container-fluid"> 
     <h1>Products</h1> 

     <table id="products" width="100%" class="display cell-border compact hover order-column row-border stripe" data-source="<%= products_url(format: "json") %>"> 
     <thead> 
      <tr> 
      <th style="text-align: center">Product ID</th> 
      <th style="text-align: center">Product Name</th> 
      <th style="text-align: center">Category</th> 
      <th style="text-align: center">Release Date</th> 
      <th style="text-align: center">Price</th> 
      <th style="text-align: center">Created At</th> 
      <th style="text-align: center">Updated At</th> 
      </tr> 
     </thead> 
     <tbody> 
     </tbody> 
     </table> 
    </div> 

    <script> 
     $(document).ready(function() { 
     $('#products').dataTable({ 
      sPaginationType: "full_numbers", 
      bJQueryUI: true, 
      bProcessing: true, 
      bServerSide: true, 
      sAjaxSource: $('#products').data('source'), 
      sDom: 'CRlfrtip', 
      bStateSave: true, 
      responsive: true 
     }) 
     }); 
    </script> 

Custom class fetching the records from server with pagination, sorting and filtering. 

`/datatables/products_datatables.rb` 

class ProductsDatatable 
    delegate :params, :link_to, :number_to_currency, to: :@view 

    def initialize(view) 
    @view = view 
    end 

    def as_json(options = {}) 
    { 
     sEcho: params[:sEcho].to_i, 
     iTotalRecords: Product.count, 
     iTotalDisplayRecords: products.total_entries, 
     aaData: data 
    } 
    end 

private 

    def data 
    products.map do |product| 
     [ 
     link_to(product.id, product), 
     product.product_name, 
     product.category, 
     product.release_date.strftime("%Y-%m-%d"), 
     number_to_currency(product.price), 
     product.created_at.strftime("%Y-%m-%d %I:%M%p"), 
     product.updated_at.strftime("%Y-%m-%d %I:%M%p") 
     ] 
    end 
    end 

    def products 
    @products ||= fetch_products 
    end 

    def fetch_products #this version genertes more optimized queries for the db 
    if params[:sSearch].present? 
     products = Product 
     .where("product_name like :search 
     or category like :search 
     or date_format(release_date, '%Y-%m-%d') like :search 
     ", search: "%#{params[:sSearch]}%" 
    ) 
     .order("#{sort_by}") 
     .page(page).per_page(per_page) 
    else 
     products = Product 
     .order("#{sort_by}") 
     .page(page).per_page(per_page) 
    end 
    products 
    end 

    def page 
    params[:iDisplayStart].to_i/per_page + 1 
    end 

    def per_page 
    params[:iDisplayLength].to_i > 0 ? params[:iDisplayLength].to_i : 10 
    end 

    def sort_by 
    columns = %W[id product_name category release_date price created_at updated_at] 
    s = String.new 
    if params[:iSortCol_0].present? 
     s = s + "," + columns[params[:iSortCol_0].to_i] + " " + sort_direction(params[:sSortDir_0]) 
    end 
    if params[:iSortCol_1].present? 
     s = s + "," + columns[params[:iSortCol_1].to_i] + " " + sort_direction(params[:sSortDir_1]) 
    end 
    if params[:iSortCol_2].present? 
     s = s + "," + columns[params[:iSortCol_2].to_i] + " " + sort_direction(params[:sSortDir_2]) 
    end 
    if params[:iSortCol_3].present? 
     s = s + "," + columns[params[:iSortCol_3].to_i] + " " + sort_direction(params[:sSortDir_3]) 
    end 
    if params[:iSortCol_4].present? 
     s = s + "," + columns[params[:iSortCol_4].to_i] + " " + sort_direction(params[:sSortDir_4]) 
    end 
    if s.empty? 
     s = columns[params[:iSortCol_0].to_i] + " " + sort_direction(params[:sSortDir_0]) 
    end 
    if s[0] == "," 
     s.slice!(0) 
    end 
    s 
    end 

    def sort_direction (n) 
    n == "desc" ? "desc" : "asc" 
    end 
end 

それに応じて@productsの内容を変更しましたか?

+0

をレンダリングするGoogleマップのためのコーヒースクリプト達成しようとしているものは非常に明確ではありません。 – faster

+0

私はインデックスメソッドを持つコントローラを持っています。ビューでは、ページされた表をレンダリングするスクリプトがあります。追加のクラスを使用して、表にレンダリングされる配列を作成します。このクラスは "/datatables/products_datatables.rb"です。このクラスがデータ配列として構築するものは、レンダリングページの2番目のスクリプトでGoogleマップにハッシュを挿入する必要があるため、インデックスメソッドのコントローラーに表示したいと考えています。 2番目のスクリプトで使用するために、そのクラスからフェッチされたデータでインデックスにハッシュを構築する必要があります。 –

+0

@Mark H.が答えると、initCompliteを定義してそこに 'json'変数を公開することができますが、docによれば、sAjaxSourceは現在のページに必要なデータの一部しか取得していません。それ以外の場合は、 'ajax' https://datatables.net/examples/data_sources/ajax.htmlが必要です。https://datatables.net/reference/option/initComplete – faster

答えて

0

であることです私がアドバイスを受けた後も同じ古い問題が残っていて、コードを修正しました。データテーブルのナビゲーションボタンを使用して、最初、最後、前、次などの別のページに移動すると、テーブルの内容はそれに応じて変更されますが、the map shows always the same first 10 productsです。

Googleマップは、テーブルにレンダリングされたコンテンツが変更されたときに変更されることはありません。どうすればこの問題を解決できますか?コードを正しく変更する方法がわからないのですか? @productsが改ページで変更されたときに、@hashのコンテンツを変更する必要があります。どのようにこれを行うことができますか?

products_controller.rb

class ProductsController < ApplicationController 
    before_action :set_product, only: [:show, :edit, :update, :destroy] 

    # GET /products 
    # GET /products.json 
    def index 

    if params[:sSearch].present? 
     @products = Product 
     .where("product_name like :search 
     or category like :search 
     or date_format(release_date, '%Y-%m-%d') like :search 
     ", search: "%#{params[:sSearch]}%" 
    ) 
     .order("#{sort_by}") 
     .page(page).per_page(per_page) 
    else 
     @products = Product 
     .order("#{sort_by}") 
     .page(page).per_page(per_page) 
    end 

    @hash = Gmaps4rails.build_markers(@products) do |product, marker| 
     marker.lat product.lat || 0.0 
     marker.lng product.lng || 0.0 
     title = product.product_name 
     marker.infowindow make_content_for_infowindow(product) 
     marker.json({:title => title}) 
    end 

    @products_data = @products.map do |product| 
     [ 
     product.id, 
     product.created_at.strftime("%Y-%m-%d %H:%M:%S %Z"), 
     product.updated_at.strftime("%Y-%m-%d %H:%M:%S %Z"), 
     product.product_name, 
     product.category, 
     product.release_date ? product.release_date.strftime("%Y-%m-%d") : nil, 
     product.price, 
     product.current_location, 
     product.lat, 
     product.lng 
     ] 
    end 

    @json = { 
     "sEcho"    => params[:sEcho].to_i, 
     "iTotalRecords"  => @products.count, 
     "iTotalDisplayRecords"=> @products.total_entries, 
     "aaData"    => @products_data.as_json 
    } 

    respond_to do |format| 
     format.html 
     format.json { render :json=> @json } 
    end 
    end 

    # GET /products/1 
    # GET /products/1.json 
    def show 
    end 

    # GET /products/new 
    def new 
    @product = Product.new 
    end 

    # GET /products/1/edit 
    def edit 
    end 

    # POST /products 
    # POST /products.json 
    def create 
    @product = Product.new(product_params) 

    respond_to do |format| 
     if @product.save 
     format.html { redirect_to @product, notice: 'Product was successfully created.' } 
     format.json { render :show, status: :created, location: @product } 
     else 
     format.html { render :new } 
     format.json { render json: @product.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    # PATCH/PUT /products/1 
    # PATCH/PUT /products/1.json 
    def update 
    respond_to do |format| 
     if @product.update(product_params) 
     format.html { redirect_to @product, notice: 'Product was successfully updated.' } 
     format.json { render :show, status: :ok, location: @product } 
     else 
     format.html { render :edit } 
     format.json { render json: @product.errors, status: :unprocessable_entity } 
     end 
    end 
    end 

    # DELETE /products/1 
    # DELETE /products/1.json 
    def destroy 
    @product.destroy 
    respond_to do |format| 
     format.html { redirect_to products_url, notice: 'Product was successfully destroyed.' } 
     format.json { head :no_content } 
    end 
    end 

    private 
    # Use callbacks to share common setup or constraints between actions. 
    def set_product 
     @product = Product.find(params[:id]) 
    end 

    # Never trust parameters from the scary internet, only allow the white list through. 
    def product_params 
     params.fetch(:product, {}) 
    end 

    def page 
     params[:iDisplayStart].to_i/per_page + 1 
    end 

    def per_page 
     params[:iDisplayLength].to_i > 0 ? params[:iDisplayLength].to_i : 10 
    end 

    def sort_by 
     #these should be enumerated in the same order as they appear rendered in the table from left to right 
     columns = %W[id created_at updated_at product_name category release_date price current_location lat lng] 
     s = String.new 
     if params[:iSortCol_0].present? 
     s = s + "," + columns[params[:iSortCol_0].to_i] + " " + sort_direction(params[:sSortDir_0]) 
     end 
     if params[:iSortCol_1].present? 
     s = s + "," + columns[params[:iSortCol_1].to_i] + " " + sort_direction(params[:sSortDir_1]) 
     end 
     if params[:iSortCol_2].present? 
     s = s + "," + columns[params[:iSortCol_2].to_i] + " " + sort_direction(params[:sSortDir_2]) 
     end 
     if params[:iSortCol_3].present? 
     s = s + "," + columns[params[:iSortCol_3].to_i] + " " + sort_direction(params[:sSortDir_3]) 
     end 
     if params[:iSortCol_4].present? 
     s = s + "," + columns[params[:iSortCol_4].to_i] + " " + sort_direction(params[:sSortDir_4]) 
     end 
     if s.empty? 
     s = columns[params[:iSortCol_0].to_i] + " " + sort_direction(params[:sSortDir_0]) 
     end 
     if s[0] == "," 
     s.slice!(0) 
     end 
     s 
    end 

    def sort_direction (n) 
     n == "desc" ? "desc" : "asc" 
    end 

    def make_content_for_infowindow(product) 
     s = String.new 
     s << "Name: " 
     s << product.product_name 
     s << " ID: " 
     s << product.id.to_s 
     s << " Category: " 
     s << product.category 
     s << " Price: " 
     s << product.price.to_s 
     s 
    end 
end 

index.html.erb

div class="container-fluid"> 
    <h1>Products</h1> 

    <table id="products" width="100%" class="display cell-border compact hover order-column row-border stripe" data-source="<%= products_url(format: "json") %>"> 
    <thead> 
     <tr> 
     <th style="text-align: center">Product ID</th> 
     <th style="text-align: center">Created At</th> 
     <th style="text-align: center">Updated At</th> 
     <th style="text-align: center">Product Name</th> 
     <th style="text-align: center">Category</th> 
     <th style="text-align: center">Release Date</th> 
     <th style="text-align: center">Price</th> 
     <th style="text-align: center">Current Location</th> 
     <th style="text-align: center">Latitude</th> 
     <th style="text-align: center">Longitude</th> 
     </tr> 
    </thead> 
    <tbody> 
    </tbody> 
    </table> 
</div> 

<div class="row-fluid"> 
    <div id="map" style='width: 100%; height: 500px; border: 1px solid black;'> 
    </div> 
</div> 

<br> 

<script> 
    $(document).ready(function() { 
    $('#products').dataTable({ 
     sPaginationType: "full_numbers", 
     bJQueryUI: true, 
     bProcessing: true, 
     bServerSide: true, 
     sAjaxSource: $('#products').data('source'), 
     sDom: 'CRlfrtip', 
     bStateSave: true, 
     responsive: true 
    }) 
    }); 
</script> 

<script type="text/javascript"> 
    buildMap (<%=raw @hash.to_json %>); 
</script> 

gmaps_google.js.coffee

class RichMarkerBuilder extends Gmaps.Google.Builders.Marker #inherit from builtin builder 
    #override create_marker method 
    create_marker: -> 
    options = _.extend @marker_options(), @rich_marker_options() 
    @serviceObject = new RichMarker options #assign marker to @serviceObject 

    rich_marker_options: -> 
    marker = document.createElement("div") 
    marker.setAttribute 'class', 'marker_container' 
    marker.innerHTML = @args.title 
    _.extend(@marker_options(), { content: marker }) 

    infobox: (boxText)-> 
    content: boxText 
    pixelOffset: new google.maps.Size(-140, 0) 
    boxStyle: 
     width: "400px" 

    # override method 
    create_infowindow: -> 
    return null unless _.isString @args.infowindow 
    boxText = document.createElement("div") 
    boxText.setAttribute("class", 'marker_info_box') #to customize 
    boxText.innerHTML = @args.infowindow 
    @infowindow = new InfoBox(@infobox(boxText)) 

@buildMap = (markers)-> 
    handler = Gmaps.build 'Google', { builders: { Marker: RichMarkerBuilder} } #dependency injection 

    #then standard use 
    handler.buildMap { provider: {}, internal: {id: 'map'} }, -> 
     markers = handler.addMarkers(markers) 
     handler.bounds.extendWith(markers) 
     handler.fitMapToBounds() 
0

私がこれを正しく読んでいるなら、あなたが提案しているものを正確に行うことはできません。あなたは2つの要求を扱っています。あなたのProductsDataTableクラスのデータやJSONをコントローラーのインスタンス変数として簡単に公開し、テンプレートのスクリプトタグのJavaScript変数に書き込むことができます。しかし、それにもかかわらず、getデータテーブルが初期化されるとすぐにJSONを呼び出します。

あなたがしようとしていることは、JavaScriptで完全に達成できるかのように見えます。 initCompleteオプションをhttps://datatables.net/reference/option/initCompleteのようにデータテーブルに渡すことができます。これは、データが取得されたときに渡されたコールバックを呼び出します。

これにより、指定したコールバック関数に渡される変数jsonで利用できるテーブルのJSONデータが作成されます。その後、コールバックでマップを初期化することができます。

0

私が期待していた解決策がここにあります。コントローラで

、コードの1行:

@json = ProductsDatatable.new(view_context).as_json 

これは、以下に、この例のような更なる処理のためにデータを利用可能にします。このJSONオブジェクトをさらに望んだとして

<%= @json %> 

とスライスとサイコロ:

あなたは全体のJSONオブジェクトを表示することができます。

Total Records Count: <%= @json[:iTotalRecords] %> 
aaData class: <%= @json[:aaData].class %> 
aaData count: <%= @json[:aaData].count %> 
aaData first class: <%= @json[:aaData].first.class %> 
aaData first content: <%= @json[:aaData].first %> 
aaData first content product Product ID (link): <%= @json[:aaData].first[0] %> 
aaData first content product Product Name: <%= @json[:aaData].first[1] %> 

問題は、現在のページ等、最初の10枚のレコードは、ページ5、7、10から現在の10件のレコードが表示されていない(表改ページを介して)変更されたとき

ここ
+0

私の前のコメントをよく読んでください。フロントエンドで作業する必要があります。新しいページを取得するたびに、コールバックを呼び出して新しいデータでマップを更新する必要があります。 – faster

+0

私はコードをさらに改訂し、解決されていないため、最初の問題の解決方法を尋ねる別のソリューションを投稿します。 –

関連する問題