Knockout.js 访问dxDataGrid中的子对象属性

Knockout.js 访问dxDataGrid中的子对象属性,knockout.js,devexpress,devextreme,Knockout.js,Devexpress,Devextreme,我正在构建一个包含大量数据网格的应用程序(多通道),但我无法在DevExtreme教程和指南中找到解决方案。 我用knockout方法实现了一个dxDataGrid,下面是我的实体: (function() { Application1.playerViewModel = function(data) { this.id = ko.observable(); this.firstname = ko.observable();

我正在构建一个包含大量数据网格的应用程序(多通道),但我无法在
DevExtreme
教程和指南中找到解决方案。
我用
knockout
方法实现了一个
dxDataGrid
,下面是我的实体:

(function() {
    Application1.playerViewModel = function(data) {
            this.id = ko.observable();
            this.firstname = ko.observable();
            this.lastname = ko.observable();
            this.fullname = ko.observable();
            this.date_of_birth = ko.observable();
            this.country = ko.observable();
            this.team = ko.observable();
            this.teamname = ko.observable();
            this.position = ko.observable();
            if(data)
                this.fromJS(data);
    };

    $.extend(Application1.playerViewModel.prototype, {
        toJS: function () {
            return {
                id: this.id(),
                firstname: this.firstname(),
                lastname: this.lastname(),
                date_of_birth: this.date_of_birth(),
                fullname: this.firstname()+" "+this.lastname,
                country: Application1.db.objectLink("countries", this.country() ? this.country().id(): undefined),
                team: Application1.db.objectLink("teams", this.team() ? this.team().id() : undefined),
                teamname: this.team().name(),
                position: Application1.db.objectLink("positions", this.position() ? this.position().id(): undefined),
            };
        },

        fromJS: function(data) {
            if(data) {
                this.id(data.id);
                this.firstname(data.firstname);
                this.lastname(data.lastname);
                this.fullname(data.firstname + " " + data.lastname);
                this.date_of_birth(data.date_of_birth);
                if(data.country)
                    this.country(new Application1.countryViewModel(data.country));
                if(data.team){
                    this.team(new Application1.teamViewModel(data.team));
                    this.teamname = data.team.name;
                }
                if(data.position)
                    this.position(new Application1.positionViewModel(data.position));
            }
        }
    });
})();
以下是视图模型:

Application1.players = function (params, viewInfo) {
    "use strict";

    var shouldReload = false,
        openCreateViewAsRoot = viewInfo.layoutController.name === "split",
        playersDataSource = new DevExpress.data.DataSource({
            store: Application1.db.players,
            map: function (item) {
                return new Application1.playerViewModel(item);
            }
        }),
        dataFieldList =  [
            { dataField: 'firstname', allowGrouping: false },
            { dataField: 'lastname', allowGrouping: false },
            { dataField: 'date_of_birth', sortIndex: 0, sortOrder: 'asc', allowGrouping: false },
            { dataField: 'country', visible: false },
            { dataField: 'team', allowGrouping: true },
            { dataField: 'position', allowGrouping: true },
            { dataField: 'fullname', visible: false, allowGrouping: false}
        ], columnChooser = { enabled: true }, allowColumnReordering = true, sorting = { mode: 'multiple' },
            groupPanel = { visible: true, emptyPanelText: 'Drag a column header here to group grid records' },
            pager = { visible: true },
            paging = { pageSize: 10 },
            editing = {
                editEnabled: true,
                editMode: 'row',
                insertEnabled: true,
                removeEnabled: true
            },
            filterRow = { visible: true },
            searchPanel = { visible: true },
            selection = { mode: 'none' } ;

    function handleplayersModification() {
        shouldReload = true;
    }

    function handleViewShown() {
        if (shouldReload) {
            shouldReload = false;
            dataSource.pageIndex(0);
            dataSource.load();
        }
    }

    function handleViewDisposing() {
        Application1.db.players.off("modified", handleplayersModification);
    }

    function refreshList() {
        dataSource.pageIndex(0);
        dataSource.load();
    }

    Application1.db.players.on("modified", handleplayersModification);

    return {
        refreshList: refreshList,
        viewShown: handleViewShown,
        viewDisposing: handleViewDisposing,
        openCreateViewAsRoot: openCreateViewAsRoot,
        players: playersDataSource,
        dataFieldList: dataFieldList,
        columnChooser: columnChooser,
        allowColumnReordering: allowColumnReordering,
        sorting: sorting,
        groupPanel: groupPanel,
        pager: pager,
        paging: paging,
        editing: editing,
        filterRow: filterRow,
        searchPanel: searchPanel,
        selection: selection
    };
};
HTML:


结果是:


我尝试将
team.name
position.name
放在配置对象
dataFieldList
数据字段中,但它返回空列。

通常,您不需要在dxDataGrid数据源中使用敲除驱动的视图模型,因为dxDataGrid提供了开箱即用的CRUD支持。因此,没有什么可以阻止您构建与列模式完全匹配的平面对象,而不是使用生成的视图模型

此外,如果您正在使用ODataContext,它将不会加载导航属性,除非您通过extend选项明确指定此属性。请阅读文档以了解详细信息

您的数据源定义可能如下所示:

playersDataSource = new DevExpress.data.DataSource({
    store: Application1.db.players,
    map: function (item) {
        return {
            firstname: item.firstname,
            lastname: item.lastname,
            date_of_birth: item.date_of_birth,
            country: item.country.name,
            team: item.team.name,
            position.item.position.name,
            fullname: item.fullname
        };
    },
    expand: ['country', 'team', 'position']
}),
更新 我之前的回答不是最好的,因为如果您以这种方式声明数据源,您将不会编辑国家、团队和职位。要支持编辑,请从数据源中删除map方法并使用列。在这种情况下,甚至不需要展开导航属性,因为它们将通过查找展开。下面是一个简短的例子:

playersDataSource = new DevExpress.data.DataSource({
    store: Application1.db.players
}),
columns:[{ 
    dataField: country, 
    lookup: { 
        dataSource: { store: Application1.db.countries }, 
        displayExpr: 'name',
        valueExpr: 'id'
    }
}]

感谢Tanner的评论,但不幸的是,team().name和team().name()不起作用,两者都返回:我认为它们在本例中返回未定义。感谢天王星,我遵循了您的第二个解决方案,结果很接近,但它没有在每行显示团队名称,结果如下:和columns对象:(我从数据源中删除了映射属性)displayExpr和valueExpr选项用于引用数据源项字段。团队项是否具有相应的字段(名称和id)?如果否,则更改displayExpr和valueExpr选项以引用现有字段。是的,它与position相同,团队具有id和name属性。这是团队视图模型:我只能假设玩家具有单独的团队id字段,并且您需要将dataField列选项设置为“团队”,而不是“团队”。如果您添加地图,则连接到数据源,您可以将断点插入此函数,并在调试器中查看项具有哪些字段。您是对的。播放器具有字段团队id,但当我将该字段放入dataField列并将“id”放入valueExpr字段时,它不起作用: