【问题标题】:Moment.js broken when Knockout.js model updated当 Knockout.js 模型更新时 Moment.js 损坏
【发布时间】:2014-08-06 11:42:45
【问题描述】:

我将 WebApi 2.o 与 Knockout.js 和 Moment.js 一起使用来解析 JSON 日期/时间。页面加载时,最初 Moments.js 工作正常。但是当我更新 Knockout ViewModel 时,Moment.js 无法以正确的方式解析 JSON 日期并显示“无效日期”错误,无论 WebApi 返回正确的 JSON 日期。 这是java脚本:

<script>
    function viewModel() {
        var self = this;
        self.currentPage = ko.observable();
        self.pageSize = ko.observable(10);
        self.currentPageIndex = ko.observable(0);
        self.schedule = ko.observableArray();
        self.currentPage = ko.computed(function () {
            var pagesize = parseInt(self.pageSize(), 10),
            startIndex = pagesize * self.currentPageIndex(),
            endIndex = startIndex + pagesize;
            return self.schedule.slice(startIndex, endIndex);
        });
        self.nextPage = function () {
            if (((self.currentPageIndex() + 1) * self.pageSize()) < self.schedule().length) {
                self.currentPageIndex(self.currentPageIndex() + 1);
            }
            else {
                self.currentPageIndex(0);
            }
        }
        self.previousPage = function () {
            if (self.currentPageIndex() > 0) {
                self.currentPageIndex(self.currentPageIndex() - 1);
            }
            else {
                self.currentPageIndex((Math.ceil(self.schedule().length / self.pageSize())) - 1);
            }
        }
        self.sortType = "ascending";
        self.sortTable = function (viewModel, e) {
            var orderProp = $(e.target).attr("data-column")
            self.schedule.sort(function (left, right) {
                leftVal = left[orderProp];
                rightVal = right[orderProp];
                if (self.sortType == "ascending") {
                    return leftVal < rightVal ? 1 : -1;
                }
                else {
                    return leftVal > rightVal ? 1 : -1;
                }
            });
            self.sortType = (self.sortType == "ascending") ? "descending" : "ascending";
        }
        //This must update ViewModel - return data for selected number of days. 
        self.getDays = function (days) {
            var uri = "/api/job?days=" + days;
            $.getJSON(uri, function (data) {
                ko.mapping.fromJS(data.$values, {}, self.schedule);
            })
            .error(function (xhr, status, error) {
                var err = eval("(" + xhr.responseText + ")");
                alert(err.Message);
            });
        }
    }
    $(document).ready(function () {
        var vm = new viewModel();
        $.ajax({
            url: "/api/job",
            type: "GET",
            cache: false,
        }).done(function (data) {
            vm.schedule(data.$values);
            ko.applyBindings(vm);
        }).error(function (xhr, status, error) {
            var err = eval("(" + xhr.responseText + ")");
            alert(err.Message);
        });
    });
</script>

这是 HTML 部分:

<div class="well well-sm">
        Find schedule for next
        <div class="btn-group">
            <button type="button" class="btn btn-default" id="7" value="7" data-bind="click: getDays.bind($data, '7')">7 days</button>
            <button type="button" class="btn btn-default" id="10" value="10" data-bind="click: getDays.bind($data, '10')">10 days</button>
            <button type="button" class="btn btn-default" id="14" value="14" data-bind="click: getDays.bind($data, '14')">14 days</button>
            <button type="button" class="btn btn-default" id="30" value="30" data-bind="click: getDays.bind($data, '30')">30 days</button>
            <button type="button" class="btn btn-default" id="60" value="60" data-bind="click: getDays.bind($data, '60')">60 days</button>
            <button type="button" class="btn btn-default" id="180" value="180" data-bind="click: getDays.bind($data, '180')">180 days</button>
        </div>
    </div>
    <table id="arrival" class="table table-condensed table-striped">
        <thead>
            <tr data-bind="click: sortTable">
                <td></td>
                <th data-column="excursion">Name</th>
                <th data-column="excursiondate">Date</th>
            </tr>
        </thead>
        <tbody data-bind="foreach: currentPage">
            <tr>
                <td><a data-bind="attr: { href: '/list/' + $data.kodg }" target="_parent">Tourist list</a></td>
                <td data-bind="text: $data.excursion"></td>
                <td data-bind="text: moment($data.excursiondate).format('DD.MM', 'ru')"></td>
            </tr>
        </tbody>
        <tfoot>
            <tr>
                <td colspan="3" class="pager">
                    <button data-bind="click: previousPage" class="btn previous"><i class="glyphicon glyphicon-backward"></i></button>
                    Page
                            <label data-bind="text: currentPageIndex() + 1" class="badge"></label>
                    <button data-bind="click: nextPage" class="btn next"><i class="glyphicon glyphicon-forward"></i></button>
                </td>
            </tr>
        </tfoot>
    </table>

这是我在第一次通话时收到的默认数据。

{"$id":"1","$values":[{"$id":"2","kodg":1406621521,"excursion":"Big Buddha Tour","excursiondate":"2014-07-31T00:00:00"},{"$id":"3","kodg":-1434407447,"excursion":"City Tour Gems","excursiondate":"2014-07-29T00:00:00"},{"$id":"4","kodg":-23317405,"excursion":"Transfer JSM","excursiondate":"2014-07-29T00:00:00"},{"$id":"5","kodg":-1035617799,"excursion":"Big Buddha Tour","excursiondate":"2014-07-26T00:00:00"},{"$id":"6","kodg":-277944785,"excursion":"City Tour Gems","excursiondate":"2014-07-25T00:00:00"},{"$id":"7","kodg":1405931911,"excursion":"City Tour Gems","excursiondate":"2014-07-22T00:00:00"},{"$id":"8","kodg":1405759887,"excursion":"City Tour Gems","excursiondate":"2014-07-20T00:00:00"},{"$id":"9","kodg":-699185234,"excursion":"Khao Lak","excursiondate":"2014-07-17T00:00:00"},{"$id":"10","kodg":2047068503,"excursion":"City Tour Gems","excursiondate":"2014-07-15T00:00:00"},{"$id":"11","kodg":164879331,"excursion":"City Tour Gems","excursiondate":"2014-07-13T00:00:00"},{"$id":"12","kodg":228070035,"excursion":"Shopping Tour","excursiondate":"2014-07-13T00:00:00"},{"$id":"13","kodg":1978323751,"excursion":"Khao Lak","excursiondate":"2014-07-10T00:00:00"}]}

这是我在使用参数调用 getDays 后收到的一组数据。

{"$id":"1","$values":[{"$id":"2","kodg":1406621521,"excursion":"Big Buddha Tour","excursiondate":"2014-07-31T00:00:00"}]}

我确实将 WebApi 类更改为如下(为了只接收字符串):

public class job
        {
            public string kodg { get; set; }
            public string excursion { get; set; }
            public string excursiondate { get; set; }
        }

但仍然有同样的问题。所以这不取决于我从 WebApi 控制器接收到的数据。

【问题讨论】:

    标签: javascript knockout.js knockout-mapping-plugin momentjs


    【解决方案1】:

    如果您可以放入 jsfiddle,它可能有助于诊断。

    我创建了一个简单的视图模型:

    function ViewModel() {
        excursionDate = ko.observable('09/22/2014 23:49:35.349');
    }
    
    ko.applyBindings(new ViewModel());
    

    还有这个html:

    <span data-bind="text: moment(this.excursionDate()).format('DD.MM', 'ru')"></span>
    

    它适用于上述日期,返回“22.09”。我也只使用 2014 年 9 月 22 日,但使用无效日期,如 09/22/2014 23:49.356,它实际上在页面上返回“无效日期”。也许您可以将数据限制在一行或某处,清理数据,调试数据,甚至使用

    <textarea data-bind="text: ko.toJSON($data)"></textarea>
    

    也许看看发生了什么,并确保你没有得到你不期望的东西。高温

    【讨论】:

    • 很难在 jsfiddle 上重复这一点,因为 JSON 数据来自托管在我们服务器上的 WebApi 控制器,因此纯 HTML 几乎不会显示真实图片。无论如何,感谢您的建议,我会尝试使用日期格式。
    • ko.ToJSON 不是我真正需要的。实际上我需要相反的结果 - 从 JSON 日期格式到“简单”表示,例如“07.08”。
    • 了解,但我担心的是您的 JSON excursiondate 数据可能不会随所有日期返回。如果您可以验证这一点,它可能会有所帮助,只是为了确保这不是问题所在。如果此数据来自 sql server,您可以通过添加诸如“where isdate(excursiondate) = 0”之类的 where 子句来运行快速查询,以返回任何不是有效日期、时间或日期时间值的执行日期。综上所述,我不相信您的代码有问题,似乎我们需要缩小问题的根源。我个人会从数据开始以确保。
    • 我确实更新了我的问题,所以你可以看到我在第一次调用时收到的数据,然后在我调用函数 getDays 时看到。让我解释。默认呼叫 - 过去 30 天和其他呼叫的数据集,使用参数(7、10 或 14 天)。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2015-09-17
    • 1970-01-01
    • 2021-04-20
    • 1970-01-01
    • 1970-01-01
    • 2014-08-21
    • 1970-01-01
    相关资源
    最近更新 更多