Kendo UI和knockout.js rowTemplate排序

时间:2013-07-17 13:02:09

标签: asp.net-mvc knockout.js kendo-ui

我有一个MVC网站,我使用Kendo UI和knockout.js来显示页面。一种情况是通过$.getJSON从服务器获取数据库信息,然后在KendoUI网格上显示此信息。

<div data-bind="kendoGrid:{sortable:true, data:users, rowTemplate:'userRowTemplate'}>
    <table>
        <thead>
            <tr>
                <th>Username</th>
                <th>First Name</th>
                <th>Last Name</th>                   
            </tr>
        </thead> </table>
</div>

<script type="text/html">
    <tr>
        <td data-bind="text: Username"></td>
        <td data-bind="text: FirstName"></td>
        <td data-bind="text: LastName"></td>            
    <tr>
</script>

和javascript:

<script type="text/javascript">
    var ViewModel = function () {
        var self=this;
        self.users=ko.mapping.fromJS([]);
        $getJSON("/UserManagementController/GetUsers",function(data){
            ko.mapping.fromJS(data,{},self.users);
        });                 
    };

    $(document).ready(function(){
        var newViewModel=new ViewModel();
        ko.applyBindings(newViewModel);
    });    
</script>

我希望这些数据可以在特定列上进行排序(这里指定的那些是例如),但我无法成功实现这一点。我尝试过this knockout-kendo plugin issue post的解决方案,该解决方案适用于简单对象,但不适用于可观察对象。所以我的问题是:如何将数据从数据库通过MVC控制器映射到淘汰赛中的观察者并在Kendo网格中显示它们,但仍能够对它们进行排序?

谢谢, 亚历克斯巴拉克

3 个答案:

答案 0 :(得分:2)

您可以通过创建JS视图模型来表示从服务器返回的数据,并将数据映射到视图模型中。然后,您可以通过订阅匹配的observable属性来设置简单对象,以实现排序。

这是一个例子: http://jsfiddle.net/R4Jys/1/

HTML:

<div data-bind="kendoGrid: gridOptions(myList)"></div>
<script id="rowTmpl" type="text/html">
    <tr>
        <td>
            <span data-bind="text: firstName" />
        </td>
        <td>
            <span data-bind="text: lastName" />
        </td>
        <td>
            <span data-bind="text: userName" />
        </td>
    </tr>
</script>

JavaScript的:

var gridItem = function () {
    var self = this;
    self.firstName = ko.observable();
    self.firstNameSort;
    self.firstName.subscribe(function (value) {
        self.firstNameSort = value;
    });
    self.lastName = ko.observable();
    self.lastNameSort;
    self.lastName.subscribe(function (value) {
        self.lastNameSort = value;
    });
    self.userName = ko.observable();
    self.userNameSort;
    self.userName.subscribe(function (value) {
        self.userNameSort = value;
    });
    self.other = ko.observable('test');
    return self;
};
var vm = function() {
    var self = this;
    self.myList = ko.observableArray();
    self.test = ko.observable();
    self.gridOptions = function (data) {
        return {
            data: data,
            rowTemplate: 'rowTmpl',
            useKOTemplates: true,
            scrollable: true,
            sortable: true,
            columns: [
                {
                    field: "firstNameSort",
                    title: "First Name",
                    width: 130
                },
                {
                    field: "lastNameSort",
                    title: "Last Name",
                    filterable: true
                },
                {
                    field: "userNameSort",
                    title: "Username"
                }
            ]
        }
    };
    var data = [{'firstName':'Steve', 'lastName':'Jones', 'userName': 'steve.jones'},
                {'firstName':'Janet', 'lastName':'Smith', 'userName': 'janet.smith'},
                {'firstName':'April', 'lastName':'Baker', 'userName': 'april.baker'},
                {'firstName':'Dave', 'lastName':'Lee', 'userName': 'dave.lee'},
                {'firstName':'Jack', 'lastName':'Bennet', 'userName': 'jack.bennet'},
                {'firstName':'Chris', 'lastName':'Carter', 'userName': 'chris.carter'}];
    self.myList(ko.utils.arrayMap(data, function(item) { 
        var g = new gridItem();
        ko.mapping.fromJS(item, {}, g);
        return g;
    }));
};
var pageVm = new vm();

ko.applyBindings(pageVm);

答案 1 :(得分:1)

作为替代方案,您可以在6844行和第6844行修改kendo.web.js(版本2013.3.1119)。 6844.

替换

compare: function(field) {
        var selector = this.selector(field);
        return function (a, b) {
                a = selector(a);
                b = selector(b);

使用

compare: function(field) {
        var selector = this.selector(field);
        return function (a, b) {
                a = ko.utils.unwrapObservable(selector(a));
                b = ko.utils.unwrapObservable(selector(b));

通过使用knockout实用程序“ko.utils.unwrapObservable”,当kendo比较列的值时,您可以获取observable的值

答案 2 :(得分:0)

DEFINE CUSTOM COMPARE FUNCTION将提供解决方案,您可以在字段定义中覆盖比较功能。

所以你可以这样做:

$("#grid").kendoGrid({
    dataSource: dataSource,
    sortable: true,
    columns: [{
        field: "item",
        sortable: {
            compare: function(a, b) {
                var valueA = a["item"];
                var valueB = b["item"];

                if (typeof valueA === "function") valueA = valueA();
                if (typeof valueB === "function") valueB = valueB();

                if (this.isNumeric(valueA) && this.isNumeric(valueB))
                {
                    valueA = parseFloat(valueA);
                    valueB = parseFloat(valueB);
                }

                if (valueA && valueA.getTime && valueB && valueB.getTime)
                {
                    valueA = valueA.getTime();
                    valueB = valueB.getTime();
                }

                if (valueA === valueB)
                {
                    return a.__position - b.__position;
                }

                if (valueA == null)
                {
                    return -1;
                }

                if (valueB == null)
                {
                    return 1;
                }

                if (valueA.localeCompare)
                {
                    return valueA.localeCompare(valueB);
                }

                return valueA > valueB ? 1 : -1;
            }
        }
    }]
});

private isNumeric(input)
    {
        return (input - 0) == input && ('' + input).trim().length > 0;
    }

比较方法是从kendo脚本中窃取的,但更改是属性是typeof函数(ko.observable是什么),它会解包该值。另外,我添加了对数字的支持。