【问题标题】:Durandal knockout jchartfxDurandal 淘汰赛 jchartfx
【发布时间】:2013-04-09 04:07:34
【问题描述】:

我正在尝试将此组件 jchartfx 与 Durandel 集成。我有一个没有 Durandel 的使用淘汰赛的独立原型,它运行良好,所以我确信这个问题与 Durandel 相关。

这是我的视图模型代码:

define(function (require) {
    var http = require('durandal/http');
    var serverUrl = '/api/burndown';
    var chart1;

    function burnDownModel() {
        var self = this;
        self.initilize = true;
        self.displayName = 'Burndown Chart';
        self.description = 'Burndown Chart';
        self.chartData = ko.observableArray([]);
        self.viewAttached = function() {

        };

        // testing with fake data
        self.activate = function () {
            return http.get(serverUrl).then(function (response) {

                for (var i = 0; i < 10; i++) {
                    var data = {
                        "Date": '2013-02-18T00:00:00',
                        "DevCurrentEstimates": 6.5,
                        "TestCurrentEstimates": 7.5,
                        "DevOriginalEstimates": 8.5,
                        "TestOriginalEstimates": 9.5
                    };


                    self.chartData.push(data);
                }

                ko.bindingHandlers.jchartFx = {
                    init: function (element, valueAccessor) {
                        chart1 = new cfx.Chart();
                        chart1.getData().setSeries(4);
                        chart1.getAxisX().getLabelsFormat().setFormat(cfx.AxisFormat.Date);
                        chart1.getAxisX().getLabelsFormat().setCustomFormat("MMM-dd");
                        debugger;

                        var value = ko.utils.unwrapObservable(valueAccessor());
                        chart1.setDataSource(value);
                        chart1.create(element);
                    }
                };
            });
        };
    };

    return burnDownModel;
});

和我的 html 绑定

<div id="ChartDiv1" class="chartdiv"  data-bind="jchartFx:chartData"style="width:550px;height:400px;display:inline-block"></div>

正如我所说,我在没有 Durandel 的情况下也能完成这项工作。

这是该解决方案的脚本:

<script type="text/javascript">

    $(function () {
        var viewModel = {
            chartDatas: ko.observableArray([])
        };
        LoadChartData();

        function LoadChartData() {
            for (var i = 0; i < 10; i++) {
                var chartData = {
                    "Date": '2013-02-18T00:00:00',
                    "DevCurrentEstimates": 6.5,
                    "TestCurrentEstimates": 7.5,
                    "DevOriginalEstimates": 8.5,
                    "TestOriginalEstimates": 9.5
                };
                viewModel.chartDatas.push(chartData);
            }
        }

        ko.applyBindings(viewModel);
    });

</script>

我能看到的唯一区别是该脚本在页面加载时运行,而且我必须手动应用 ko 绑定,而不是 Durandel 为我执行此操作。 我没有收到任何错误,只是没有显示图表数据。

【问题讨论】:

  • 我不确定图表未呈现的确切原因,但这似乎与 DOM 时间有关。如果您将chart1.create(element) 调用放在像setTimeout(function () { chart1.create(element); }, 100); 这样的setTimeout 中,它似乎可以工作。
  • jchartfx 假设它使用完整的 DOM。在 Durandal 中,绑定是相对于在初始绑定之前尚未成为 DOM 一部分的文档片段的。

标签: knockout.js durandal jchartfx knockout-extensions


【解决方案1】:

在您的代码中,首先将 chartData 更改为 Observable。 jchartfx 需要一个对象数组(json),而不是对象数组。我将单个数组传递给 chartData observable。

将“更新”添加到您的 Knockout bindingHandler 并在那里执行图表创建方法。当您从 viewModel 中的 viewAttached 方法或 afterBind 获取数据时,这将被触发。由于 viewAttached 在 Durandal 绑定到 DOM 之后,您的图表将按预期显示。

视图模型文件

define(function (require) {

    var system = require('durandal/system');
    var http = require('durandal/http');

    // KO observables & bindings
    var errorMessage = "";
    var pageTitle = "jChartFX Demo";
    var chartData = ko.observable();

    function LoadServerData() {

        // Your server request can go here;
        var items = [{
            "Date": '2013-02-18T00:00:00',
            "DevCurrentEstimates": 6.5,
            "TestCurrentEstimates": 7.5,
            "DevOriginalEstimates": 8.5,
            "TestOriginalEstimates": 9.5
        },{
            "Date": '2013-02-18T00:00:00',
            "DevCurrentEstimates": 6.5,
            "TestCurrentEstimates": 7.5,
            "DevOriginalEstimates": 8.5,
            "TestOriginalEstimates": 9.5
        },{
            "Date": '2013-02-18T00:00:00',
            "DevCurrentEstimates": 6.5,
            "TestCurrentEstimates": 7.5,
            "DevOriginalEstimates": 8.5,
            "TestOriginalEstimates": 9.5
        }]
       chartData(items);
    }

    var activate = function(view) {
        system.log("view activated");
        return;
    }

    var viewAttached = function (view) {
        LoadServerData();
        system.log("viewAttached loaded");
        return;
    }

    return {
        pageTitle: pageTitle,
        chartData: chartData,
        activate: activate,
        viewAttached: viewAttached
    }
});

ko.bindingHandlers.jchartFx = {
    init: function (element, valueAccessor) {
        chart1 = new cfx.Chart();
        chart1.getData().setSeries(4);
        chart1.getAxisX().getLabelsFormat().setFormat(cfx.AxisFormat.Date);
        chart1.getAxisX().getLabelsFormat().setCustomFormat("MMM-dd");
        debugger;
    },
    update: function (element, valueAccessor) {
        var value = ko.utils.unwrapObservable(valueAccessor());
        chart1.setDataSource(value);
        chart1.create(element);
    }
};

和视图文件

<div>
    <h2 data-bind="text: pageTitle"></h2>
    <div id="ChartDiv1" class="chartdiv" data-bind="jchartFx: chartData" style="width:550px;height:400px;display:inline-block"></div>
</div>

【讨论】:

    【解决方案2】:

    问题似乎与尚未附加到 DOM 的视图有关。

    一种可能的解决方案是在您的 viewModel 中创建一个属性来指示视图是否已附加,并修改绑定,以便在附加视图之前不会创建图表。

    //in view model
    isViewAttached = ko.observable(false);
    self.viewAttached = function () {
        self.isViewAttached(true);
    };
    
    
    //in binding
    ko.bindingHandlers.jchartFx = {
        init: function (element, valueAccessor, allBindingsAccessor, viewModel) {
            ...
            viewModel.isViewAttached.subscribe(function () {
                $(element).chart();
            });
            ...
    

    不过,这可能不是最好的主意,因为它依赖于视图模型中的“神奇”属性。

    更好的方法可能是创建一个辅助绑定,您可以直接绑定到 isViewAttached 属性,并通过 allBindingsAccessor 参数从 jchartFx 绑定访问它。这样一来,所有的视图模型属性依赖项都是公开的,并且更容易判断发生了什么。

    无论如何,我强烈建议将绑定移出激活函数 - 理想情况下移入在首次加载应用程序时执行的全局脚本中。您真的只想设置一次ko.bindingHandlers.jchartFx - 另外,您可能希望在其他视图模型中使用它。

    【讨论】:

      猜你喜欢
      • 2014-08-01
      • 2015-02-24
      • 2017-11-03
      • 2015-02-24
      • 2014-04-11
      • 2014-08-21
      • 2013-08-12
      • 2014-12-13
      • 2014-08-30
      相关资源
      最近更新 更多