0

私のバックグラウンドは主に asp.net/c# で、Durandal/Knockout は初めてです。オブジェクトのリストを表示し、1 つのアイテムを選択すると、選択したアイテムのデータを表示するビューを作成しようとしています。私の問題は、返されるデータが選択されたアイテムが常に最後のアイテムのデータであることです。

以下、私の見解ですが、

... マークアップは表示されません

<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>

そして私のビューモデルの一部:

var convenio = function (id, nome, cidade, cnpjcpf, servicosativos) {

    self = this;

    self.idformatado = ko.observable("[" + id + "]");
    self.id = ko.observable(id);
    self.nome = ko.observable(nome);
    self.cidade = ko.observable(cidade);
    self.cnpjcpf = ko.observable(cnpjcpf);
    self.servicosativos = ko.observable(servicosativos);
    self.estiloativo = ko.computed(function () {
        if (self.servicosativos() > 0)
            return 'grd-convenio-detalhe-ativo';
        else
            return 'grd-convenio-detalhe-inativo';
    });
    self.convenioselecionado = ko.observable("");
    return self;

};

var convenios = ko.observableArray([]);
var tamanho = ko.observable("0");
var convenioselecionado = ko.observable("");
var pesquisacodigo = ko.observable("");
var pesquisanome = ko.observable("");
var pesquisacidade = ko.observable("");

var filtrar = function () {

 ... Retrieve data from Database and pushes data into convenios observablearray
            $.each(resultado.pesquisa.retorno, function (i, item) {
                convenios.push(new convenio(item.idconveniado, item.nome, item.cidade, item.cnpjcpf, item.servicosativos));
            });


};

alterarCadastro = function (selecionado) {
    if (selecionado && selecionado.id()) {
        alert(selecionado.nome());
    }
};


var viewAttached = function(view) {
    bindEventToList(view, '.grd-convenio-detalhe', alterarCadastro);
};

var bindEventToList = function (rootSelector, selector, callback, eventName) {
    var eName = eventName || 'click';
    $(rootSelector).on(eName, selector, function () {
        var selecionado = ko.dataFor(this);
        callback(selecionado);
        return false;
    });
};


return {
    convenios: convenios,
    filtrar: filtrar,
    tamanho: tamanho,
    pesquisacodigo: pesquisacodigo,
    pesquisanome: pesquisanome,
    pesquisacidade: pesquisacidade,
    alterarCadastro: alterarCadastro,
    displayName: 'Convênio',
    viewAttached: viewAttached

}

});});

ビューは期待どおりに表示されますが、アイテムを選択すると、bindEventTolist 関数で返されるデータ (ko.datafor) は常に最後のアイテムのデータになります。私は何を間違っていますか?これは、この種のアプリへの良いアプローチですか? ティア。

4

2 に答える 2

0

アイテムがクリックされたときに新しいビューを表示したい場合は、新しいアイテム ビュー ルートをデュランダル ルーターにスプラットで追加できます (例: router.mapNav('item/:id'))。新しいルートにリンクします。このようなもの:

<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>

個人的には、アイテム固有のすべてのロジックを新しいルートのビューモデルに渡すことにより、単一の責任の原則に従うため、このソリューションを好みます。

于 2013-06-26T14:17:48.203 に答える
0

http://jsfiddle.net/yQgAm/8/

あなたのフィドルを更新しましたが、かなり時間がかかりました:)

あなたはそれを必要以上に難しくしていたので、あなたのコードにマークアップを入れて、私が変更したものをすべて覚えていればそれを表示しようとしています。私が戻って行った最大のことの 1 つは、camelCase を使用してメソッドの名前を変更し、タイプミスがないようにすることでした。次に、viewModel から parter 関数を取り出しました。これは、それ自体がクラスであり、そこで定義する必要がないためです。

次に、ビュー モデルに self = this のスコープを与えました。これは、ビューモデルに、その内部に自己があることを知らせるだけです。先行者は、このスコープの一部として定義されています。

次に、私は jsFiddle のマスターではなく、jQuery ($.each) と KnockOut (ko.) の両方を使用しようとしていたので、$.each を ko.utils.arrayForEach() という KnockOut ユーティリティに置き換えました。これは基本的に同じです。もの。

コードで $.each を使用して forEach ループを実行していたときに、selectedPartner の値として値を設定していたのではないかと思います。

元のコードの一部を再利用したい場合、私が提案する最大のことは、非常に多くのライブラリへの依存を取り除くことです。基本的な JavaScript を理解しようとしながら、jQuery、Knockout、Durandal を同時に学習する (仮定) ことで、あなたは自分自身を混乱させています。一度に 1 つずつ実行しないと、理由が 100% わからないことを行うコードが大量に作成されることになります。

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>

viewAttached は、ビューのアタッチが完了し、何かを実行できることをルーターに知らせるデュランダル メソッドであるため、div にクリック バインディングを配置しました。作成した bindToEventList は、名前を付けたクラスの何かがクリックされてそのメソッドが起動されたかどうかを示しているだけです。それはすべて使いやすく、より効率的ですが、KnockOut を学んでいるだけなら、最初にバインディングの仕組みを学ぶことをお勧めします。

于 2013-06-27T01:15:40.370 に答える