Question

I'm just getting blank areas where the charts should be when I use pdfkit to generate pdf's of pages containing highcharts charts.

my controller code looks like:

html = render_to_string(:template => "pages/pdf", :layout => false, :formats => :html)
kit = PDFKit.new(html)
send_data(kit.to_pdf, :filename => "results.pdf", :type => "application/pdf", :disposition => "inline")

pages/pdf.html.haml

!!! 5
%html
  %head
    %title
    %meta{:charset => "UTF-8"}
    <script src="/javascripts/jquery.min.js" type="text/javascript"></script>
    <script src="/javascripts/highcharts.js" type="text/javascript"></script>
    :css
      ...
  %body
    .results-container
      .results-inner
        .results_graph
          = render :partial => "pages/graph"
        .priorities-overview
          - @priorities.each do |priority|
            .priority
              .title-graphic
                %h3
                  = priority.title
                .graph
                  = render :partial => "pages/priority", :object => priority
                  .legend
                    %span
                      Score
                    = "#{priority.score.to_i}/100"

pages/graph.html.erb

<div id="resultGraph" class="graph bar-graph"></div>
<div id="graphLines"><div class="line"><div class="num">100</div></div><div class="line"><div class="num">75</div></div><div class="line center"><div class="num">50</div></div><div class="line"><div class="num">25</div></div><div class="line"><div class="num">0</div></div></div>
<script>
$(function(){

    var options = {
        chart: {
            renderTo: 'resultGraph',
            backgroundColor: 'transparent',
            type:'column',
            padding: [0, 0, 0, 0],
            margin: [0, 10, 50, 30]
        },
        title: {
          text: null
        },
        credits:{
            enabled: false
        },
        legend: {
            enabled: false
        },
        //series: [{
        //  name: "Scores",
        //  data: <%= @priorities.pluck('score - 50') %>
        //}],
        series: [],
        xAxis: {
          categories: <%=raw @priorities.pluck(:title) %>,
      lineWidth: 0,
      gridLineWidth: 0,
      minorGridLineWidth: 0,
      gridLineColor: 'transparent',
      lineColor: 'transparent',
      minorGridLineColor: 'transparent',
      minorTickLength: 0,
      tickLength: 0,
      minPadding: 0,
      title: {
        enabled: false
      }
    },
    yAxis: {
      lineWidth: 0,
      gridLineWidth: 0,
      minorGridLineWidth: 0,
      gridLineColor: 'transparent',
      lineColor: 'transparent',
      minorGridLineColor: 'transparent',
      minorTickLength: 0,
      tickLength: 0,
      minPadding: 0,
      title: {
        text: null
      },
      min: -50,
      max: 50,
      endOnTick: true,
      labels:{
        enabled: false
      }
    },
    tooltip: {
        enabled: false
    },
    plotOptions: {
        series: {
            pointPadding: 0,
            groupPadding: 0,
            borderWidth: 1,
            shadow: false,
            zIndex: 9,
            enableMouseTracking: false,
            shadow: false,
            animation: false,
            states: {
                hover: {
                    enabled: false
                }
            }
        },
        bar: {
            zIndex: 9
        }
    }
    };

    var data = <%= @priorities.pluck('score - 50') %>;
    var series = {
        data: []
    };
    $.each(data, function(itemNo, item){
        var data = {};
        data.y = parseFloat(item);
        if(item > 40){
            data.color = "#8dc53e";
        } else if(item > 30) {
            data.color = "#b5d558";
        }
        else if(item > 20) {
            data.color = "#c8eb58";
        }
        else if(item > 10) {
            data.color = "#dbe622";
        }
        else if(item > 0) {
            data.color = "#facc40";
        }
        else if(item > -10) {
            data.color = "#faaf40";
        }
        else if(item > -20) {
            data.color = "#f7931e";
        }
        else if(item > -30) {
            data.color = "#f05a29";
        }
        else if(item > -40) {
            data.color = "#ee4136";
        }
        else if(item >= -50) {
            data.color = "#cd392b";
        }
        series.data.push(data);
    });
  options.series.push(series);

  var chart1 = new Highcharts.Chart(options);
});
</script>

If I use render_to_string(:template => "pages/pdf", :layout => false, :formats => :html) in the controller without the send_data line, the charts display fine (but the layout is still rendering...could that be a problem?)

I don't know what I'm doing wrong here. Any ideas? Thanks.

Was it helpful?

Solution

Crap workaround:

def pdf
  @user = User.find(params[:id])
  @priorities = @user.priorities.order("score desc")
  render "pages/pdf", :layout => false
end

def results_pdf
  if user_signed_in?
    @user = current_user
    @priorities = @user.priorities.order("score desc")
    FileUtils.mkdir_p "#{Rails.root.to_s}/public/results/#{@user.id.to_s}/pdf"
    system("wkhtmltopdf.sh http://[site].com/pdf/#{@user.id.to_s} #{Rails.root.to_s}/public/results/#{@user.id.to_s}/result.pdf")
    redirect_to "/results/#{@user.id.to_s}/result.pdf"
  else
    redirect_to "/login"
  end
end

Basically, the pdf action just renders the HTML with the graphs visible, then results_pdf uses wkhtmltopdf directly to make the PDF from the regular HTML page. Not sure why pdfkit wouldn't display the graphs using the same HTML that the page is displaying, but whatever,

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top