Knockout.js 如何获取所选项目数据?

Knockout.js 如何获取所选项目数据?,knockout.js,Knockout.js,我的背景主要是asp.net/c,我对Durandal/Knockout还不熟悉。我试图构建一个视图来显示对象列表,并在选择一个项目时显示所选项目的数据。我的问题是,无论选择什么项目,返回的数据总是最后一个项目的数据 以下是我的看法 ... 未显示标记 <div data-bind="visible: convenios().length > 0" style="height:30px"> Pesquisa retornou <span data-bind="text

我的背景主要是asp.net/c,我对Durandal/Knockout还不熟悉。我试图构建一个视图来显示对象列表,并在选择一个项目时显示所选项目的数据。我的问题是,无论选择什么项目,返回的数据总是最后一个项目的数据

以下是我的看法

... 未显示标记

<div data-bind="visible: convenios().length > 0" style="height:30px">
Pesquisa retornou <span  data-bind="text: convenios().length"></span> conveniados.
</div>
<div class="row-fluid">
    <section  class="grd-convenio" data-bind="foreach: convenios" style="width:25%; height:300px; overflow-y: scroll">
        <article>
        <div class="grd-convenio-detalhe"  title="Clique para alterar">
            <span class="grd-convenio-nome" data-bind="text: nome"></span>
            <span class="grd-convenio-id" data-bind="text: id"></span><br/>
            <span class="grd-convenio-cidade" data-bind="text: cidade"></span>
            <span class="grd-convenio-ativo" data-bind="text: servicosativos"></span>
        </div>
        </article>        

    </section>
</div>
})),


视图按预期显示,但当我选择任何项时,bindEventTolist函数中返回的数据(ko.datafor)始终是最后一项的数据。我做错了什么?这是这种应用的好方法吗?TIA.

如果您希望在单击项目时显示新视图,可以使用splat(例如router.mapNav('item/:id'))将新项目视图路由添加到durandal路由器,然后更改标记以包含指向新路由的链接。大概是这样的:

<section  class="grd-convenio" data-bind="foreach: convenios" style="width:25%; height:300px; overflow-y: scroll">
        <article>
        <a class="grd-convenio-detalhe" title="Clique para alterar" data-bind="attr: {href: '#/item/' + $data.id}">
            <span class="grd-convenio-nome" data-bind="text: nome"></span>
            <span class="grd-convenio-id" data-bind="text: id"></span><br/>
            <span class="grd-convenio-cidade" data-bind="text: cidade"></span>
            <span class="grd-convenio-ativo" data-bind="text: servicosativos"></span>
        </a>
        </article>        

    </section>

我个人更喜欢此解决方案,因为它遵循单一责任原则,将所有特定于项目的逻辑处理到新路线的viewmodel。

我更新了你的小提琴,但花了不少时间:)

你让它变得比需要的更难,所以我尝试在你的代码上添加一些标记,以显示我所做的更改,如果我能记住的话。我回去做的最大的一件事就是使用camelCase重命名您的方法,以确保不存在拼写错误。接下来,我将parter函数从viewModel中删除,因为它本身就是一个类,不需要在其中定义

然后我给你的视图模型一个self=this的范围。这只是让视图模型知道,其中的任何内容都有一个self。前身定义为此范围的一部分

接下来,因为我不是JSFIDLE大师,而您试图同时使用jQuery($.each)和KnockOut(ko),所以我将$.each替换为一个名为ko.utils.arrayForEach()的KnockOut实用程序,这基本上是一样的

我怀疑,当您使用$执行forEach循环时,代码中的每一个都将该值设置为selectedPartner的值,然后当您显示selectedPartner时,它只是显示您在forEach循环中设置的最后一个值

如果您想获取一些原始代码并重新使用它,我建议您做的最大的事情就是删除对这么多库的依赖。在试图理解基本JavaScript的同时,同时学习jQuery、Knockout和Durandal,这让您感到困惑。一步一个脚印地做,否则你会得到很多代码,这些代码做的事情你都不知道为什么

function partner(id, name) {
    var self = this;
    self.id = ko.observable(id);
    self.pName = ko.observable(name);
}

function viewmodel() {
   var self = this;
   self.initialdata = ko.observableArray([
       { id: 1, name: "name1" } ,
       { id: 2, name: "name2" } ,
       { id: 3, name: "name3" } ,
       { id: 4, name: "name4" } ,
   ]);

    self.partners = ko.observableArray();  
    self.selectedPartner = ko.observable();  

    self.loadData = function () {
        self.partners([]);
        ko.utils.arrayForEach(self.initialdata(), function (item) {
            self.partners.push(new partner(item.id, item.name));
        });
    };
    self.showSelectedPartner = function (selected) {
        alert(selected.pName());
    }
}

ko.applyBindings(new viewmodel());
你的看法呢

<section>
    <div>
        <button data-bind="click: loadData">Load Data</button>
    </div>
    <div data-bind="visible: partners().length > 0" >Query returned <span data-bind="text: partners().length"></span> records</div>
    <div>
        <section data-bind="foreach: partners" >
            <article>
                <div title="Click to Update" data-bind="click: $parent.showSelectedPartner"> <span data-bind="text: id"></span>  
 <span data-bind="text: pName"></span>
                </div>
            </article>
        </section>
    </div>
</section>

加载数据
查询返回的记录

我在你的div上放了一个点击绑定,因为viewAttached是一个Durandal方法,让路由器知道视图已经完成了连接,它可以做一些事情。您创建的bindToEventList只是说,如果单击了与您命名的类相关的任何内容,就会触发该方法。这一切都很好用,而且效率更高,但如果您只是在学习KnockOut,我建议您首先学习绑定的工作原理

“返回最后一项数据”是什么意思?您的警报设置为显示单击的内容,但它不会对该数据做任何操作。@kadumel这就是问题所在。警报始终显示最后一个项目的属性“nome”,而不是实际单击项目的属性“nome”。我需要获取点击项目的id以显示其数据,但由于我总是获取最后一个项目的数据,所以我还没有做任何事情。我只是显示一个返回“nome”的警报。由于语言的差异,理解代码有点困难,但是出于所有目的,您的alert()应该显示当前对象。你能不能制作一个小提琴来重新制作这个问题,这样我们就可以看到背景中发生了什么?抱歉@kadumel。虽然js代码还可以,但我无法让小提琴工作。你知道,我对所有这些工具都不熟悉。但是如果你想看一下[小提琴]()。我相信这会帮助你理解。我点击的任何物品,alert总是返回'name4'。@kadumel,我在小提琴[新小提琴]上做了一点小改动(),谢谢@jaq316。创建一个视图来处理该项可能是一个解决方案,但我真正想找到的是一种将对象“convenio”绑定到单击的元素的方法。ko.数据用于(本);始终返回集合中最后一个“convenio”对象,而不是单击的对象。非常感谢。我真的很感激你的提示和建议。使用您的JSFIDLE,我成功地修复并运行了我的原始代码。我打算在不久的将来在Durandal/Knockout中开发应用程序,我需要快速学习。关于这个问题,我将多读一些书。谢谢你@Kadumel。我确实理解Durandal代码,并且对它很满意。我只是不知道应该使用哪一个,单击binding还是Durandal事件处理程序。顺便说一句,真正修复我的原始代码的是将initialData声明为可观察数组。再次感谢你。很酷回答了你的问题你可以接受答案。祝你好运
<section>
    <div>
        <button data-bind="click: loadData">Load Data</button>
    </div>
    <div data-bind="visible: partners().length > 0" >Query returned <span data-bind="text: partners().length"></span> records</div>
    <div>
        <section data-bind="foreach: partners" >
            <article>
                <div title="Click to Update" data-bind="click: $parent.showSelectedPartner"> <span data-bind="text: id"></span>  
 <span data-bind="text: pName"></span>
                </div>
            </article>
        </section>
    </div>
</section>