0

次のように、ノックアウト マッピング プラグインをダウンロードしたビューモデルに新しいオブジェクトを追加しようとしています。

<script type="text/javascript">
    var myViewModel = {};

    var Fighter = function (data) {
        var self = this;
        self.Name = ko.observable(data.Name);
        self.Country = ko.observable(data.Country);
        self.TopSpeed = ko.observable(data.TopSpeed);
    };

    var WarCraft = function (data) {
        var self = this;
        self.fighter = ko.observable(data.fighter);
    };

    var dataMappingOptions = {
        key: function (data) {
            return data.id;
        },
        create: function (options) {
            if (data.id == 1)
                return new Fighter(options.data);
            else
                if (data.id == 2)
                    return new WarCraft(options.data);
        }
    };

    $.getJSON("/Home/GetServerData", function (model) {
        ko.mapping.fromJS(model, dataMappingOptions, myViewModel);

        ko.applyBindings(myViewModel);

    }).error(function () { alert("Oops!") }).success(function () { alert("Yeah!") });


    myViewModel.AddToData = function () {
        var newFighter = new Fighter(
                        {
                            id : 1,
                            Name: myViewModel.warCraft.fighter.Name(),
                            Country: myViewModel.warCraft.fighter.Country(),
                            TopSpeed: myViewModel.warCraft.fighter.TopSpeed() 
                        });
        var newWarCraft = new WarCraft({ id: 2, fighter: newFighter });
        myViewModel.WW2Machines.push(newWarCraft);
    }.bind(myViewModel);


</script>

サーバー側モデル:

 DataModel model = new DataModel();
 model.warCraft = new WarCraft();
 model.warCraft.fighter = new Fighter();
 model.warCraft.fighter.Name = "Spitfire";
 model.WW2Machines = new List<WarCraft>();

 WarCraft w1 = new WarCraft();
 w1.fighter = new Fighter() { Name = "Spitfire" };
 model.WW2Machines.Add(w1);

 WarCraft w2 = new WarCraft();
 w2.fighter = new Fighter() { Name = "Hurricane" };
 model.WW2Machines.Add(w2);

 WarCraft w3 = new WarCraft();
 w3.fighter = new Fighter() { Name = "Tomcat" };
 model.WW2Machines.Add(w3);

... データを初期化して送信する Ajax 呼び出しによって呼び出されるメソッド:

DataModel model = new DataModel();
model.warCraft = new WarCraft();
model.warCraft.fighter = new Fighter();
model.warCraft.fighter.Name = "Spitfire";
model.WW2Machines = new List<WarCraft>();

WarCraft w1 = new WarCraft();
w1.fighter = new Fighter() { Name = "Spitfire" };
model.WW2Machines.Add(w1);

WarCraft w2 = new WarCraft();
w2.fighter = new Fighter() { Name = "Hurricane" };
model.WW2Machines.Add(w2);

WarCraft w3 = new WarCraft();
w3.fighter = new Fighter() { Name = "Tomcat" };
model.WW2Machines.Add(w3);

return Json(model, JsonRequestBehavior.AllowGet);

. . . そして私のhtml:

<div id="show" data-bind="visible: WW2Machines().length>0">
    <h2>Information Display:</h2>
    NewNumber : <span data-bind="text: WW2Machines().length"></span>
    <ul data-bind="foreach: WW2Machines">
        <li>
            Name: <span data-bind="text: fighter.Name"></span>
            <br>&nbsp;</br>
        </li>
    </ul>
</div>

<div id="theForm">
    @using (Html.BeginForm())
    {
        <legend WW2 Fighter Planes: >
            <fieldset>
                Name:
                <br>&nbsp;</br>
                <select data-bind="value: warCraft.fighter.Name, optionsCaption: 'Please Select . . '">
                    <option>Mosquito</option>
                    <option>Mustang</option>
                    <option>Messerschmidt 109</option>
                </select>
                <br>&nbsp;</br>
                <span data-bind="text: warCraft.fighter.Name"></span>
                <br>&nbsp;</br>

                Country:
                <br>&nbsp;</br>
                <select data-bind="value: warCraft.fighter.Country, optionsCaption: 'Please Select . . '">
                    <option>England</option>
                    <option>USA</option>
                    <option>Germany</option>
                </select>
                <br>&nbsp;</br>
                <span data-bind="text: warCraft.fighter.Country"></span>
                <br>&nbsp;</br>

                Top Speed:
                <br>&nbsp;</br>
                <select data-bind="value: warCraft.fighter.TopSpeed, optionsCaption: 'Please Select . . '">
                    <option>390 km/h</option>
                    <option>275 km/h</option>
                    <option>250 km/h</option>
                </select>
                <br>&nbsp;</br>
                <span data-bind="text: warCraft.fighter.TopSpeed"></span>                

                <input type="button" data-bind="click: AddToData">Add</input>

            </fieldset>

        </legend>

}

問題は、[追加] ボタンがトリガーされ、行が空であることを除いて、表示領域に行が追加されることです。Firefox のデバッガー コンソールでは、サーバーから送信された行と、[追加] ボタンによって追加された行 (データが正しく含まれている) の両方を参照できることがわかりますが、1 つの不可解な違いがあります。次の構文で既存の行を取得します。

myViewModel.WW2Machines()[0].fighter.Name()

. . . そして、この構文で追加された行:

myViewModel.WW2Machines()[3].fighter().Name()

. . . また、それぞれの添字の構文を相互に交換すると、エラーがスローされます。これは、行が空白として追加される理由の手がかりになるかもしれませんが、その理由はわかりませんか? 誰でも助けてもらえますか?

4

2 に答える 2

0

エイドリアン、マッピング プラグインが WarCraft.fighter を監視可能にしない理由を説明してもらえますか? プラグインのデフォルトを使用してマップされたすべてのオブジェクトとサブプロパティは観察可能だと思いました。ありがとう、

于 2013-07-03T12:31:09.010 に答える
0

少なくともいくつかの問題 (および、一番下に出くわしている不可解な違いの説明) は、後で追加する行がWarCraft.fighter、マッピング プラグインが行っていないオブザーバブルを作成することです。

したがって、これを交換できます:

var WarCraft = function (data) {
    var self = this;
    self.fighter = ko.observable(data.fighter);
};

このため

var WarCraft = function (data) {
    var self = this;
    self.fighter = data.fighter;
};

マップされたデータと追加されたデータの両方に同じ方法でアクセスできるはずです。

myViewModel.WW2Machines()[0].fighter.Name()
于 2013-07-03T06:11:17.237 に答える