Как преобразовать [объект Object] в Backbone в фактические данные

У меня есть функция в моем представлении Backbone (file.js), которая заполняется ответом JSON в следующем формате: -

Функция в Backbone View: -

chart_data: function(){
    var all_stats = this.collection.toJSON();
    $("#page-container").html(this.users_by_loc({
        platform_stats: all_stats,
        graph_data: all_stats.items.slice(0,5) 
        // I want to use the top 5 entries to plot graph
    }));
}

Ответ присутствует как часть all_stats (из моего вызова API - я использую Rails на стороне сервера): -

{
   "items":
   [
       {
           "loc": "Chennai",
           "users": 11707
       },
       {
           "loc": "Hyderabad",
           "users": 4327
       },
       {
           "loc": "Pune",
           "users": 3625
       },....(many more entries)

   ]
}

Теперь я пытаюсь передать ответ json, присутствующий в параметре graph_data (определенный в моем представлении Backbone выше), в переменную с именем chartData. который определен в моем шаблоне jst.ejs (код ниже). Эта переменная (chartData) используется моим JS-кодом AM-диаграмм для построения графика.

Мой файл jst.ejs, в котором есть код для заполнения данных графика и построения графика, выглядит следующим образом: -

<script>
    var chart;  

    chartData = "<%= graph_data %>"    
    console.log("chartData: ", chartData);

            AmCharts.ready(function () {
                // SERIAL CHART
                chart = new AmCharts.AmSerialChart();
                chart.dataProvider = chartData;

                //additional code to help plot the chart  

                chart.write("chartdiv");
            });

</script>

<div id="chartdiv" style="width: 60%; height: 400px;"></div>

Моя текущая связка заключается в том, что когда я…

chartData = "<%= graph_data %>"    
console.log("chartData: ", chartData);

.. в моем шаблоне jst.ejs переменная chartData вместо фактических данных как части all_stats (shown_above) возвращает в моей консоли firebug следующее: -

chartData: [object Object],[object Object],[object Object],[object Object],[object Object]

Как мне правильно назначить фактические данные, представленные в переменной graph_data (как часть моего основного представления), переменной chartData присутствует в моем шаблоне jst.ejs для построения графика?


person boddhisattva    schedule 04.09.2013    source источник
comment
Почему вы вообще используете <script> внутри шаблона? Почему бы не сделать JavaScript в JavaScript?   -  person mu is too short    schedule 04.09.2013
comment
@muistooshort: Я думаю, вы правы, я не думал об этом раньше. Скажем, я пишу логику рисования диаграммы в моем представлении Backbone (файл js), мне нужно будет только написать <div id="chartdiv" style="width: 60%; height: 400px;"></div> в моем шаблоне Backbone (файл jst.ejs), и будет ли это работать?   -  person boddhisattva    schedule 05.09.2013
comment
Наверное. Вам просто нужно будет в нужный момент вызвать диаграмму в представлении Backbone.   -  person mu is too short    schedule 05.09.2013
comment
@muistooshort: Я пытаюсь это сделать, но проблема, с которой я сейчас столкнулся, - это chart.write("chartdiv");, присутствующая в моем представлении Backbone, не распознающая chartdiv в шаблоне. Могу ли я просто назначить данные как часть моей функции диаграмм AM 2, атрибут chart.dataProvider n реализовать оставшееся вещество 2 нарисовать диаграмму в моем шаблоне jst.ejs? Если да, то как мне передать объект, которым я манипулирую в своей функции диаграмм AM, в качестве параметра для шаблона, чтобы я мог использовать его позже. 2 Нарисуйте график d. При таком подходе диаграмма будет распознана как часть логики рисования в шаблоне.   -  person boddhisattva    schedule 05.09.2013
comment
Если вызывающий собирается сразу же поместить представление в DOM, посмотрите информацию _.defer или setTimeout(..., 0).   -  person mu is too short    schedule 05.09.2013
comment
@muistooshort: То, что мне нужно, сработало :). Большое тебе спасибо. Пожалуйста, опубликуйте свои предложения в качестве ответа, чтобы я мог их принять.   -  person boddhisattva    schedule 05.09.2013
comment
@muistooshort - функция _.defer или setTimeout отлично работает, когда я обновляю страницу, но поскольку я использую одностраничное приложение, большинство моих запросов являются вызовами AJAX. Диаграмма не загружается, когда я перехожу из другой части приложения в то место, где ожидается загрузка диаграммы. Есть идеи, что мне может не хватать? Когда я использовал console.log, я вижу, что как часть запроса AJAX он входит в функцию, в которой я рисую диаграмму, но chartdiv по-прежнему остается пустым.   -  person boddhisattva    schedule 05.09.2013
comment
Я ничего не знаю об amchart, поэтому в основном делаю догадки.   -  person mu is too short    schedule 06.09.2013
comment
@muistooshort - на основании информации, полученной из этой ссылки, мне пришлось прокомментировать из следующих строк в моем представлении Backbone JS: - AmCharts.ready(function () { и });. После этого диаграмма отобразилась соответствующим образом. Пожалуйста, опубликуйте свой ответ, чтобы я мог его принять.   -  person boddhisattva    schedule 06.09.2013
comment
Вы можете ответить на свои вопросы и принять эти ответы, в конце концов, вы сделали большую часть работы.   -  person mu is too short    schedule 06.09.2013
comment
Ладно, выигрываешь, завтра напишу правильный ответ :)   -  person mu is too short    schedule 08.09.2013
comment
@muistooshort: Спасибо :). Я помню эту цитату из фильма «A Beautiful Mind», никто не побеждает… Я считаю, что это применимо и здесь… Я просто честен :). Хорошо, я надеюсь, что наша ветка комментариев скоро прекратится :), очень скоро ... когда-нибудь нас предупредят перенаправить эту ветку в чат:) ... Я уже видел подобное сообщение ранее, связанное с нашей текущей цепочкой .. Ваше здоровье!:)   -  person boddhisattva    schedule 09.09.2013


Ответы (1)


Смешивание «настоящего» кода JavaScript с вашими шаблонами (т. Е. Добавление <script> в шаблон, а не простых фрагментов JavaScript для объединения шаблона) обычно не работает так хорошо. Вам, как правило, будет легче, если вы разделите проблемы: элементы HTML помещаются в шаблон, функциональность подключается к представлению.

Я не так хорошо знаком с amChart, но многим библиотекам диаграмм (и картографии) необходимо знать несколько важных вещей об их целевом элементе, прежде чем они смогут выполнять какую-либо работу. В частности, они обычно хотят знать, где он находится на странице и насколько он велик, и они не узнают, пока <div> не будет отображен на странице. В приложении Backbone это обычно неверно, пока кто-то render не добавит представление и не добавит его el на страницу:

var v = new View;
// We don't know the position or size of anything yet.
v.render();
// We still don't know.
$('body').append(v.el);
// Now the size and position are available but we might have to
// pass control back to the browser first.

Вы сталкиваетесь с дополнительными трудностями, связанными с тем, что amChart, по-видимому, хочет id чего-то в DOM, в которое он должен втягиваться:

chart.write("chartdiv");

Но document.getElementById('chartdiv') не вернет ничего полезного до тех пор, пока не будет вызван render и кто-то не выполнил x.append(v.el) (или эквивалент).

Если вы ожидаете, что кто-то сразу же el вашего представления на страницу сразу после вызова render, вы можете поставить в очередь некоторый код для запуска после того, как браузер вернет управление (и, следовательно, у вас будет время, чтобы определить размер и положение вещей и сделать document.getElementById('chartdiv') сделать что-нибудь полезное), используя setTimeout с нулевым таймаутом:

render: function() {
    var _this = this;
    var chartData = ....

    // Do normal rendering and template stuff.

    setTimeout(function() {
        var chart = new AmCharts.AmSerialChart();
        chart.dataProvider = chartData;
        //...
        chart.write("chartdiv");
    }, 0);
    return this;
}

Вы также можете использовать _.defer (что немногим больше, чем setTimeout(..., 1)), если хотите более подробно рассказать Это.

Возможно, придется разобраться с некоторыми специфическими для amChart вещами, но, надеюсь, это позаботится о сложных частях.

Кстати, этот AmCharts.ready вызов, который вы упомянули в комментариях, вероятно, не так хорошо работает с одностраничными приложениями, потому что он, вероятно, эквивалентен $(document).ready() и срабатывает только при загрузке страницы (т.е. только один раз в течение одностраничного приложение). Вместо этого вы можете использовать другие события, но вы должны иметь возможность использовать существующую структуру представления Backbone вместо того, чтобы полагаться на события, готовые для документа.

person mu is too short    schedule 09.09.2013