24

HtmlHelperビューにHTMLを出力する拡張機能を作成しようとしています。このHTMLでは、KnockoutJSバインディングをいくつか接続しています。私はKOに慣れていないので、まだいくつかのことを成し遂げるのに苦労しています。とにかく、私がやろうとしているのは、クライアント側のコードでオブザーバブルにバインドされた入力フィールド(サーバー側のコードで)を生成し、非表示のフィールドの値を介してオブザーバブルの初期値を設定することです。残念ながら、それは私にはうまくいきません。だから私はこれを成し遂げることができる方法があるかどうか疑問に思っています(私がそれを完全に異なってしなければならないとしても)。

これが私が基本的にしていることです:

私のクライアントサイドビューモデルには、次のものがあります。

self.dataSource = ko.observable();
self.pageSize = ko.observable();

そして私の拡張メソッドは以下を出力します:

<input type="hidden" value="/Employee/Get" data-bind="value: dataSource" />
<input type="hidden" value="30" data-bind="value: pageSize" />

しかし、ページがレンダリングされるとき、要素を調べるvalueと、入力フィールドのが空の文字列に設定されていることに気付きます。これは、オブザーバブルが宣言されている方法によるものだと思います。しかし、この動作などをオーバーライドする方法はありますか?

4

4 に答える 4

23

ここで少し遅れます。RPの答えは、ノックアウトの宣言型の性質を壊すため、実際には満足していませんでした。具体的には、valueWithInitを使用してプロパティを定義する場合、それを以前のバインディングで使用することはできません。これが彼のjsfiddleのフォークです。

同じように使用しますが、それでも内部でドキュメント全体の宣言型です。

<input data-bind="valueWithInit: firstName" value="Joe" />

アイデアを拡張して、これを使用して初期化とバインディングを分離することもできます。

<input data-bind="initValue: lastName, value: lastName" value="Smith" />

これは少し冗長ですが、組み込みのバインディングの代わりにプラグインを使用している場合に役立ちます。

<input data-bind="initValue: lastName, myPlugin: lastName" value="Smith" />

もう少し拡張して、チェックボックスを初期化する方法も必要でした。

<input type="checkbox" data-bind="checkedWithInit: isEmployed" checked />

そして、ここにハンドラーがあります:

ko.bindingHandlers.initValue = {
    init: function(element, valueAccessor) {
        var value = valueAccessor();
        if (!ko.isWriteableObservable(value)) {
            throw new Error('Knockout "initValue" binding expects an observable.');
        }
        value(element.value);
    }
};

ko.bindingHandlers.initChecked = {
    init: function(element, valueAccessor) {
        var value = valueAccessor();
        if (!ko.isWriteableObservable(value)) {
            throw new Error('Knockout "initChecked" binding expects an observable.');
        }
        value(element.checked);
    }
};

ko.bindingHandlers.valueWithInit = {
    init: function(element, valueAccessor, allBindings, data, context) {
        ko.applyBindingsToNode(element, { initValue: valueAccessor() }, context);
        ko.applyBindingsToNode(element, { value: valueAccessor() }, context);
    }
};

ko.bindingHandlers.checkedWithInit = {
    init: function(element, valueAccessor, allBindings, data, context) {
        ko.applyBindingsToNode(element, { initChecked: valueAccessor() }, context);
        ko.applyBindingsToNode(element, { checked: valueAccessor() }, context);
    }
};

valueWithInit単に内部で使用していることに注意initValueしてください。

jsfiddleで実際に動作することを確認してください。

于 2014-02-11T23:24:02.030 に答える
21

コードを少しすっきりさせるために使用できる1つの代替方法は、要素の現在の値で初期化することによって値のバインディングをラップするカスタムバインディングを使用することです。

ビューモデルにオブザーバブルが存在しない場合は、オブザーバブルを作成することもできます。

バインディングは次のようになります。

ko.bindingHandlers.valueWithInit = {
    init: function(element, valueAccessor, allBindingsAccessor, data) {
        var property = valueAccessor(),
            value = element.value;

        //create the observable, if it doesn't exist 
        if (!ko.isWriteableObservable(data[property])) {
            data[property] = ko.observable();
        }

        data[property](value);

        ko.applyBindingsToNode(element, { value: data[property] });
    }
};

次のように使用します。

<input value="someValue" data-bind="valueWithInit: 'firstName'" />

プロパティ名は引用符で囲まれていることに注意してください。これにより、未定義の値からエラーが発生するのではなく、プロパティ名が存在しない場合でも、バインディングでプロパティ名を作成できます。

サンプルは次のとおりです:http://jsfiddle.net/rniemeyer/BnDh6

于 2012-08-27T03:03:33.660 に答える
2

カスタムバインディングが重すぎる場合、簡単な解決策はDOMからオブザーバブルを初期化することです。

たとえば、次のHTMLフォームがあるとします。

<form name="person">
  <input type="text" name="firstName" value="Joe" data-bind="value: firstName"/>
</form>

次に、ノックアウトを次のように初期化できます。

ko.applyBindings({
  firstName: ko.observable(document.forms['person']['firstName'].value)
});
于 2017-01-01T22:22:10.007 に答える
1

カスタムバインディングを使用して、既存のオブザーバブルに値を割り当てることができます。

ko.bindingHandlers.yourBindingName = {
    init: function (element, valueAccessor, allBindings, viewModel, bindingContext) {
        viewModel.dataSource($(".dataSource").val());
        viewModel.pageSize($(".pageSize").val());
    }
};

次に、クラスまたはIDを入力とdata-bind="yourBindingName"それらを含むHTML要素に追加するだけです。

于 2017-07-07T07:36:45.970 に答える