1

我目前正在开发一个网站 spa 应用程序并尝试使用 knockout.js。它在一个 mvc 平台上,一个 dbdatacontroller api 使用数据和 javascript 视图模型的结果。我有一个复杂的视图模型并且遇到了困难,主要是因为是新手。我最大的问题似乎是访问 observables。数据库是这样组织的:

    function AdvanceSearch(data) {
var self = this;
self.AdvanceSearchID = ko.observable(data.AdvanceSearchID);
self.FieldTypeEnum = ko.observable(data.FieldTypeEnum);
self.AnswerType = ko.observable(data.AnswerType);
self.UserValues = ko.observableArray(ko.utils.arrayMap(data.UserValues, function (item) {
    return new UserValue(item);
}));
upshot.addEntityProperties(self, "AdvanceSearch:#A.Lib.Repository");
};

function UserValue(data) {
var self = this;

self.UserProfileID = ko.observable(data.UserProfileID);
self.LoginID = ko.observable(data.LoginID);
self.AdvanceSearchID = ko.observable(data.AdvanceSearchID);
self.FieldValueCount = ko.observable(data.FieldValueCount);
self.FieldValueText = ko.observable(data.FieldValueText);
    upshot.addEntityProperties(self, "UserValue:#A.Lib.Repository");
});
};


function AnswerType(data) {
var self = this;
self.AnswerTypeID = ko.observable(data.AnswerTypeID);
self.AnswerTypeText = ko.observable(data.AnswerTypeText);
self.Answers = ko.observableArray(ko.utils.arrayMap(data.Answers, function (item) {
    return new Answer(item);
}));
self.AnswerSliders = ko.observableArray(ko.utils.arrayMap(data.AnswerSliders, function (item) {
    return new AnswerSlider(item);
}));
upshot.addEntityProperties(self, "AnswerType:#A.Lib.Repository");
}

function Answer(data) {
var self = this;
self.AnswerTypeID = ko.observable(data.AnswerTypeID);
self.AnswerEnum = ko.observable(data.AnswerEnum);
self.AnswerText = ko.observable(data.AnswerText);
upshot.addEntityProperties(self, "Answer:#A.Lib.Repository");
}

function AnswerSlider(data) {
var self = this;
self.SliderID = ko.observable(data.SliderID);
self.AnswerTypeID = ko.observable(data.AnswerTypeID);
self.SliderType = ko.observable(data.SliderType);
self.Seed = ko.observable(data.Seed);
upshot.addEntityProperties(self, "AnswerSlider:#A.Lib.Repository");
}

我的视图模型就是这样的:

function ASViewModel() {
// Private
var self = this;
var dataSourceOptions = {
    providerParameters: {
        url: "/api/Dating",
        operationName: "GetDatingProfile"
    },
    entityType: "AdvanceSearch:#A.Lib.Repository",
    bufferChanges: false,
    mapping: AdvanceSearch
};

// Public Properties
self.dataSource = new upshot.RemoteDataSource(dataSourceOptions)
                            .refresh();
self.AdvanceSearchs = self.dataSource.getEntities();
}

所以我的标记类似于

    <ol data-bind="foreach: AdvanceSearch">
   <!-- ko if: FieldTypeEnum()===5 -->
       <select data-bind="options: AnswerType().Answers, optionsText: 'AnswerText', optionsValue: 'AnswerEnum', optionsCaption: 'Not Specified', value: UserValues().FieldValueText"></select>
   <!-- /ko -->
    <!-- ko if: FieldTypeEnum()===11 -->
        <input type="text" class="multilinetext" data-bind="attr: { id: 'value_'+AdvanceSearchID()}, value: UserValues().FieldValueText" />
    <!-- /ko -->

所以基本上,无论我做什么,我似乎都无法访问项目的值。我访问过一个分支的任何地方,即。AdvanceSearch().AnswerType().Answers,试图得到$parents[1].UserValues[].FieldValueText似乎总是不确定的。就像我说的,我是淘汰赛的新手,所以我可能只是错过了一些东西。还是我应该使用多个视图模型或类似的东西?(如果是这样,我该怎么做?)谢谢。

4

2 回答 2

0

您的:

<ol data-bind="foreach: AdvanceSearch">

需要是:

<ol data-bind="foreach: AdvanceSearchs">

注意 AdvanceSearch 到AdvanceSearchs的复数形式

编辑:

此外,UserValues它是一个 Observable 数组,因此您无法访问UserValues().FieldValueText.

请注意确切地确定您的预期输出是什么,但这会显示每个输入UserValue

<!-- ko foreach: UserValues -->
    <input type="text" class="multilinetext" data-bind="attr: { id: 'value_'+UserProfileID()}, value: FieldValueText" />
<!-- /ko -->

注意:我已经将输入的 ID 更改为其他内容以避免重复的 ID——这假设UserProfileID每个 ID 都是唯一的UserValue

更远,

能否请您参考Knockouts options-binding的文档。select元素的数据绑定选项是:

options:- 这是将select元素绑定到的选项列表

optionsText:对于列表中的每个项目,要在select元素中显示的属性

optionsCaption:select元素的第一个/“虚拟”项的文本

value:这应该是一个可观察的并且绑定到select元素的当前选择

value绑定是 Knockout 的一个非常方便的功能。它消除了担心 ID 的需要——因此optionsValue——因为您可以访问整个选定的对象。

所以你的select绑定看起来像:

<select data-bind="options: AnswerType().Answers,
                   optionsText: 'AnswerText',
                @* optionsValue: 'AnswerEnum', *@
                   optionsCaption: 'Not Specified',
                   value: selectedAnswer"></select>

假设您已向视图模型添加了一个 observable selectedAnswer

于 2012-10-01T09:45:58.300 回答
0

根据您的评论,我想我现在知道您要做什么。我将把它抽象化,以便更容易理解,因为您的 ViewModel 和对象非常复杂,如果没有解释就不容易理解。

如果您有对象类型BookAuthor构造函数:

function Book(data) {
    this.ISBN = ko.observable( data.ISBN );
    this.Title = ko.observable( data.Title );
    this.AuthorID = ko.observable( data.AuthorID );
    /* other properties */
}

function Author(data) {
    this.AuthorID = ko.observable( data.AuthorID );
    this.Name = ko.observable( data.Name );
    /* other properties */
}

要从select框中选择一本书并将input显示绑定到作者姓名,您将需要视图模型:

var vm = {};
vm.books = ko.observableArray( /* initial data */ );
vm.authors = ko.observableArray( /* initial data */ );
vm.selectedBook = ko.observable(null);
vm.selectedBooksAuthor = ko.computed( function() {
    var authors = vm.authors(),
        selectedBook = vm.selectedBook();
    if( !selectedBook ) return null; // cannot get .AuthorID() if selectedBook == null
    var id = selectedBook.AuthorID();
    for( var a in authors ) {
        if( authors[a].AuthorID() == id )
            return authors[a];
    }
})

还有你的 HTML:

<select data-bind="options: books,
                   optionsText: 'Title',
                   optionsCaption: 'Select a book...',
                   value: selectedBook"></select>
<!-- ko with: selectedBooksAuthor -->
<input type="text" data-bind="value: Name" />
<!-- /ko -->

请注意,这在大量数据上可能会变得非常低效——考虑为您的computed observableie使用更好的搜索算法(而不是此处使用的“线性”)selectedBooksAuthor

编辑:

请参阅此小提琴以进行工作演示。

于 2012-10-01T17:28:20.950 回答