Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Is orthogonal data supported with this gem? #269

Closed
gs2589 opened this issue Dec 13, 2017 · 10 comments
Closed

Is orthogonal data supported with this gem? #269

gs2589 opened this issue Dec 13, 2017 · 10 comments
Assignees
Labels

Comments

@gs2589
Copy link

gs2589 commented Dec 13, 2017

In my data table I have the following column definition:

columns:[
       {data: "supplier",
             render: function(data, type, row){
              return data ? data.name : null
             }
]

In my SearchResultDatatable#data method I have

def data
    records.map do |record|
      {
        supplier: {name: record.supplier.try(:name)},
        
      }
end

This is not working - I get the datatables.net/tn/4 error because

{name: record.supplier.try(:name)}

gets serialized as a string not an object- so data.name returns undefined.

Any thoughts on how to fix this?

@n-rodriguez
Copy link
Member

Add this in your JS:

data = JSON.parse(data);

@n-rodriguez n-rodriguez self-assigned this Feb 18, 2018
@gs2589
Copy link
Author

gs2589 commented Mar 14, 2018

Thanks n-rodriguez.
I tried your suggestion, but got this error:

Uncaught SyntaxError: Unexpected token # in JSON at position 0
at JSON.parse ()
at eval (eval at format (purchases:12), :1:6)
at format (purchases:265)
at HTMLTableCellElement. (purchases:355)
at HTMLTableSectionElement.dispatch (jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:5227)
at HTMLTableSectionElement.elemData.handle (jquery.self-bd7ddd393353a8d2480a622e80342adf488fb6006d667e8b42e4c0073393abee.js?body=1:4879)

It looks like the issue arises because of the #sanitize method

def sanitize(data)
      data.map do |record|
        if record.is_a?(Array)
          record.map { |td| ERB::Util.html_escape(td) }
        else
          record.update(record){ |_, v| ERB::Util.html_escape(v) }
        end
      end
    end

Is there a way to go around this?
Is it a bad idea to bypass this method?
Is there a way to get standard serialization into json?

@gs2589
Copy link
Author

gs2589 commented Mar 21, 2018

Ok, Im making some progress:

Here is some new code:

def data
    records.map do |record|
      {id: record.id,
       scan_timestamp: raw({data:record.effective_date.in_time_zone('Eastern Time (US & Canada)').strftime("%I:%M%p %Z %d-%b-%y"), display:"hello"}.to_json)
end

then in js, I can do
data = JSON.parse(row.scan_timestamp)
and that converts it into an object. Im wondering if there is a way to format the data in Datatable#data to ensure that the js datatables automatically turns orthogonal data into nested objects?

Thanks!

@MrMoins
Copy link

MrMoins commented Mar 23, 2018

I'm also trying to use orthogonal data but can't figure how to do with this gem.

@MrMoins
Copy link

MrMoins commented Mar 26, 2018

I'm trying to modify sanitize method like this, it return a json object correctly formatted but now I've some issue on JS side.

def sanitize(data)
  data.map do |record|
    if record.is_a?(Hash)
      record
    elsif record.is_a?(Array)
      record.map { |td| ERB::Util.html_escape(td) }
    else
      record.update(record){ |_, v| ERB::Util.html_escape(v) }
    end
  end
end

@gs2589
Copy link
Author

gs2589 commented Apr 4, 2018

@n-rodriguez Any thoughts on this?
I'd love to figure out a 'standard' way to do this with this gem and add it to the readme. Orthogonal data is pretty core to datatables, so I think many users would benefit. I'd be happy to write up the guide for the readme, at this moment, I've not been able to get this to work.

@n-rodriguez
Copy link
Member

n-rodriguez commented May 10, 2018

Hi! It could be supported. Nowadays the data is assumed to be html content so it's html escaped to avoid XSS attacks. What you want is json all the way so :

Override the sanitize method in your datatable :

  def data
    records.map do |record|
      {
        id:    record.id,
        title: { title: record.title }
      }
    end
  end

  private

    def sanitize(data)
      data.map do |record|
        if record.is_a?(Array)
          record.map { |td| ERB::Util.html_escape(td) }
        elsif record.is_a?(Hash)
          if options[:json_content]
            record
          else
            record.update(record) { |_, v| ERB::Util.html_escape(v) }
          end
        end
      end
    end

and in the controller :

  def index
    respond_to do |format|
      format.html
      format.json { render json: PostDatatable.new(params, json_content: true) }
    end
  end

And in Coffee/JS :

$ ->
  $('#posts-datatable').dataTable
    processing: true
    serverSide: true
    ajax: $('#posts-datatable').data('source')
    pagingType: 'full_numbers'
    columns: [
      { data: 'id' }
      {
        data: 'title',
        render: (data, type, row)->
          console.log(data)
          if data?
            data.title
          else
            ''
      }
    ]

@n-rodriguez
Copy link
Member

n-rodriguez commented May 10, 2018

BTW I would use https://github.com/jbox-web/ajax-datatables-rails#using-view-decorators to avoid this kind of lengty methods :

# before
def data
  records.map do |record|
    {
      id: record.id,
      scan_timestamp: raw({ data: record.effective_date.in_time_zone('Eastern Time (US & Canada)').strftime("%I:%M%p %Z %d-%b-%y"), display:"hello" }.to_json
    }
  end
end

# after
def data
  records.map do |record|
    {
      id: record.id,
      scan_timestamp: { data: record.decorate.effective_date, display: 'hello' }
    }
  end
end

@n-rodriguez
Copy link
Member

@calaway
Copy link

calaway commented Mar 31, 2019

I'm trying to specify a data-sort (or data-order) tag on a column and can't quite get it working from these instructions. Can you help me see what I've done wrong?

  def data
    records.map do |record|
      {
        id: record.id,
        build_number: { display: record.build_number, sort_by: record.build_number.to_i },
      }
    end
  end
$(document).ready(function(){
  $('#builds-datatable').DataTable({
    // ...
    columns: [
      { data: "id"},
      { data: "build_number",
        render: {
          _: 'display',
          sort: 'sort_by',
       }
      }
    ]
  });
});

display is showing correctly, but I can't get it to add the data-sort attribute. I know both display and sort_by are coming through to the client side correctly, since I can access both of them.

I have added json_content: true to the controller and copied the sanitize method into the datatable class.

Any help you can offer is greatly appreciated. Thank you for creating and maintaining such a useful gem!

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

4 participants