ASP.NET MVC ViewModelでknockout.jsを使用する方法


129

バウンティ

久しぶりですが、未だにいくつかの未解決の質問があります。バウンティを追加することで、これらの質問に答えられることを願っています。

  1. knockout.jsでHTMLヘルパーをどのように使用しますか
  2. 機能させるためにドキュメントの準備が必要だった理由(詳細については、最初の編集を参照してください)

  3. ビューモデルでノックアウトマッピングを使用している場合、どのようにすればよいですか?マッピングのため機能が無いので。

    function AppViewModel() {
    
        // ... leave firstName, lastName, and fullName unchanged here ...
    
        this.capitalizeLastName = function() {
    
        var currentVal = this.lastName();        // Read the current value
    
        this.lastName(currentVal.toUpperCase()); // Write back a modified value
    
    };
  4. たとえば、ユーザーがリクエストをキャンセルした場合のように、オブザーバブルをロールバックできるようにしたいプラグインを使用したいのですが、最後の値に戻れるようにしたいのです。私の研究から、これは編集可能のようプラグインを作っている人々によって達成されているようです

    マッピングを使用している場合、そのようなものをどのように使用しますか?私はビューマニュアルマッピングにあるメソッドに行きたくありません。インラインMJavaScriptをできるだけ少なくしたいので、各MVC viewModeフィールドをKOモデルフィールドにマップしました。なぜそのマッピングが好きなのか。

  5. この作業を(マッピングを使用して)簡単に行うと、KOの能力が大幅に失われるのではないかと心配していますが、一方で、手動マッピングは多くの作業であり、ビューに多くの情報が含まれ、将来的には維持が難しくなる可能性があります(たとえば、MVCモデルのプロパティを削除した場合、KOビューモデルでも移動する必要があります)


元の投稿

私はasp.net mvc 3を使用していて、かなりクールに見えるのでノックアウトを調べていますが、asp.net mvc、特にビューモデルでどのように機能するかを理解するのに苦労しています。

今私はこのようなことをしています

 public class CourseVM
    {
        public int CourseId { get; set; }
        [Required(ErrorMessage = "Course name is required")]
        [StringLength(40, ErrorMessage = "Course name cannot be this long.")]
        public string CourseName{ get; set; }


        public List<StudentVm> StudentViewModels { get; set; }

}

私は、CourseNameのようないくつかの基本的なプロパティを持つVmを用意し、その上にいくつかの簡単な検証を行います。Vmモデルには、必要に応じて他のビューモデルも含まれる場合があります。

次に、このVmをビューに渡して、HTMLヘルパーを使用してユーザーに表示するのを助けます。

@Html.TextBoxFor(x => x.CourseName)

Student View Modelsのコレクションからデータを取得するために、foreachループまたは何かがあるかもしれません。

次に、フォームを送信するときに、jqueryを使用serialize arrayして、それをビューモデルにバインドするコントローラーアクションメソッドに送信します。

knockout.jsを使用すると、viewmodelが取得され、HTMLヘルパーを使用しないことがわかったすべての例から、すべてが異なります。

knockout.jsでMVCのこれら2つの機能をどのように使用しますか?

私はこのビデオを見つけましたが簡単に(ビデオの最後の数分@ 18:48)、基本的にはViewModelの値を割り当てられるknockout.jsビューモデルを持つインラインスクリプトを使用して、ビューモデルを使用する方法に入ります。

これが唯一の方法ですか?ビューモデルのコレクションを含む私の例ではどうですか?すべての値を抽出してノックアウトに割り当てるには、foreachループなどが必要ですか?

HTMLヘルパーに関しては、ビデオはそれらについて何も語っていません。

これらの2つの領域は、多くの人がそれについて話しているようには見えないため、私を混乱させる2つの領域であり、例が単なるハードコードされた値の例である場合に、初期値とすべてがどのように表示されるかについて混乱します。


編集する

私はDarin Dimitrovが提案したことを試していますが、これはうまくいくようです(ただし、彼のコードにいくつかの変更を加える必要がありました)。なぜドキュメントレディを使用しなければならなかったのか分かりませんが、どういうわけかそれなしではすべてがレディではありませんでした。

@model MvcApplication1.Models.Test

@{
    Layout = null;
}

<!DOCTYPE html>

<html>
<head>
    <title>Index</title>
    <script src="../../Scripts/jquery-1.5.1.js" type="text/javascript"></script>
    <script src="../../Scripts/knockout-2.1.0.js" type="text/javascript"></script>
    <script src="../../Scripts/knockout.mapping-latest.js" type="text/javascript"></script>
   <script type="text/javascript">

   $(function()
   {
      var model = @Html.Raw(Json.Encode(Model));


// Activates knockout.js
ko.applyBindings(model);
   });

</script>

</head>
<body>
    <div>
        <p>First name: <strong data-bind="text: FirstName"></strong></p>
        <p>Last name: <strong data-bind="text: LastName"></strong></p>
        @Model.FirstName , @Model.LastName
    </div>
</body>
</html>

私はそれを動作させる準備ができているjqueryドキュメントの周りにラップする必要がありました。

私もこの警告を受けます。それが何なのかわからない。

Warning 1   Conditional compilation is turned off   -> @Html.Raw

だから私は少なくともいくつかの遊んだときにこれがどのように機能するかを更新すると私が推測する出発点を持っています。

インタラクティブチュートリアルを試してみますが、代わりにViewModelを使用します。

これらの部分に取り組む方法がまだわからない

function AppViewModel() {
    this.firstName = ko.observable("Bert");
    this.lastName = ko.observable("Bertington");
}

または

function AppViewModel() {
    // ... leave firstName, lastName, and fullName unchanged here ...

    this.capitalizeLastName = function() {
        var currentVal = this.lastName();        // Read the current value
        this.lastName(currentVal.toUpperCase()); // Write back a modified value
    };


編集2

最初の問題を理解することができました。2番目の問題についての手がかりはありません。それでも。誰かアイデアはありますか?

 @model MvcApplication1.Models.Test

    @{
        Layout = null;
    }

    <!DOCTYPE html>

    <html>
    <head>
        <title>Index</title>
        <script src="../../Scripts/jquery-1.5.1.js" type="text/javascript"></script>
        <script src="../../Scripts/knockout-2.1.0.js" type="text/javascript"></script>
        <script src="../../Scripts/knockout.mapping-latest.js" type="text/javascript"></script>
       <script type="text/javascript">

       $(function()
       {
        var model = @Html.Raw(Json.Encode(Model));
        var viewModel = ko.mapping.fromJS(model);
        ko.applyBindings(viewModel);

       });

    </script>

    </head>
    <body>
        <div>
            @*grab values from the view model directly*@
            <p>First name: <strong data-bind="text: FirstName"></strong></p>
            <p>Last name: <strong data-bind="text: LastName"></strong></p>

            @*grab values from my second view model that I made*@
            <p>SomeOtherValue <strong data-bind="text: Test2.SomeOtherValue"></strong></p>
            <p>Another <strong data-bind="text: Test2.Another"></strong></p>

            @*allow changes to all the values that should be then sync the above values.*@
            <p>First name: <input data-bind="value: FirstName" /></p>
            <p>Last name: <input data-bind="value: LastName" /></p>
            <p>SomeOtherValue <input data-bind="value: Test2.SomeOtherValue" /></p>
            <p>Another <input data-bind="value: Test2.Another" /></p>

           @* seeing if I can do it with p tags and see if they all update.*@
            <p data-bind="foreach: Test3">
                <strong data-bind="text: Test3Value"></strong> 
            </p>

     @*took my 3rd view model that is in a collection and output all values as a textbox*@       
    <table>
        <thead><tr>
            <th>Test3</th>
        </tr></thead>
          <tbody data-bind="foreach: Test3">
            <tr>
                <td>    
                    <strong data-bind="text: Test3Value"></strong> 
<input type="text" data-bind="value: Test3Value"/>
                </td>
            </tr>    
        </tbody>
    </table>

コントローラ

  public ActionResult Index()
    {
              Test2 test2 = new Test2
        {
            Another = "test",
            SomeOtherValue = "test2"
        };

        Test vm = new Test
        {
            FirstName = "Bob",
            LastName = "N/A",
             Test2 = test2,

        };
        for (int i = 0; i < 10; i++)
        {
            Test3 test3 = new Test3
            {
                Test3Value = i.ToString()
            };

             vm.Test3.Add(test3);
        }

        return View(vm);
    }

2
:私はちょうど別の同様の質問に答えるためにブログの記事を書かれているroysvork.wordpress.com/2012/12/09/...それは完全にあなたの質問に答えることはできませんが、それはあなたに物事が仕事ができるかの良いアイデアを与えます。私はこれについて、それほど遠くない将来にさらなる投稿を続けたいと思います。さらに詳しい情報が必要な場合は、投稿のコメントまたはこちらからコメントをお寄せください。
コードを超えて

回答:


180

私はすべての質問をまとめたと思います。何か見逃した場合はお知らせください(すべての質問を1か所にまとめることができればいいです =))

注意。ko.editable追加されたプラグインとの互換性

完全なコードをダウンロードする

knockout.jsでHTMLヘルパーをどのように使用しますか

これは簡単:

@Html.TextBoxFor(model => model.CourseId, new { data_bind = "value: CourseId" })

どこ:

  • value: CourseIdコントロールのプロパティをモデルおよびスクリプトモデルのvalueプロパティにバインドしていることを示しますinputCourseId

結果は次のとおりです。

<input data-bind="value: CourseId" data-val="true" data-val-number="The field CourseId must be a number." data-val-required="The CourseId field is required." id="CourseId" name="CourseId" type="text" value="12" />

機能させるためにドキュメントの準備が必要だった理由(詳細については、最初の編集を参照してください)

readyイベントを使用してモデルをシリアル化する必要がある理由はまだわかりませんが、それは単に必要であるようです(ただし、心配する必要ありません)。

ビューモデルでノックアウトマッピングを使用している場合、どのようにすればよいですか?マッピングのため機能が無いので。

私が正しく理解している場合は、KOモデルに新しいメソッドを追加する必要があります。

詳細については、「さまざまなソースからのマッピング」セクションをご覧ください。

function viewModel() {
    this.addStudent = function () {
        alert("de");
    };
};

$(function () {
    var jsonModel = '@Html.Raw(JsonConvert.SerializeObject(this.Model))';
    var mvcModel = ko.mapping.fromJSON(jsonModel);

    var myViewModel = new viewModel();
    var g = ko.mapping.fromJS(myViewModel, mvcModel);

    ko.applyBindings(g);
});

受け取っていた警告について

警告1条件付きコンパイルがオフになっている-> @ Html.Raw

引用符を使用する必要があります

ko.editableプラグインとの互換性

もっと複雑になると思っていましたが、モデルを編集可能にするには、次の行を追加するだけで統合が非常に簡単であることがわかります(この場合、サーバーとサーバーの混合モデルを使用していることに注意してください)クライアントに拡張機能を追加すると、編集可能ファイルは単純に機能します...それは素晴らしいことです):

    ko.editable(g);
    ko.applyBindings(g);

ここからあなただけのために必要なプレー例えば、私はこのように私のフィールドの編集を開始し、このボタンで、私は編集処理を開始するためのボタンがあり、プラグインによって追加の拡張機能を使用して、バインディングと:

    this.editMode = function () {
        this.isInEditMode(!this.isInEditMode());
        this.beginEdit();
    };

次に、次のコードを使用してボタンをコミットおよびキャンセルします。

    this.executeCommit = function () {
        this.commit();
        this.isInEditMode(false);
    };
    this.executeRollback = function () {
        if (this.hasChanges()) {
            if (confirm("Are you sure you want to discard the changes?")) {
                this.rollback();
                this.isInEditMode(false);
            }
        }
        else {
            this.rollback();
            this.isInEditMode(false);
        }
    };

最後に、フィールドが編集モードかどうかを示す1つのフィールドがあります。これは、単にenableプロパティをバインドするためです。

this.isInEditMode = ko.observable(false);

配列の質問について

Student View Modelsのコレクションからデータを取得するために、foreachループまたは何かがあるかもしれません。

次に、フォームを送信するときに、jqueryを使用して配列をシリアル化し、それをビューモデルにバインドするコントローラーアクションメソッドに送信します。

KOでも同じことができます。次の例では、次の出力を作成します。

ここに画像の説明を入力してください

基本的にここで、あなたは二つのリスト、使用して作成したHelpersとKOでバインドさを、彼らが持っているdblClickときは、あなたが投稿したときに、現在のリストから選択した項目を削除し、他のリストに追加し、解雇することをバインドさイベントController、それぞれの内容をリストはJSONデータとして送信され、サーバーモデルに再アタッチされます

ナゲット:

外部スクリプト

コントローラーコード

    [HttpGet]
    public ActionResult Index()
    {
        var m = new CourseVM { CourseId = 12, CourseName = ".Net" };

        m.StudentViewModels.Add(new StudentVm { ID = 545, Name = "Name from server", Lastname = "last name from server" });

        return View(m);
    }

    [HttpPost]
    public ActionResult Index(CourseVM model)
    {
        if (!string.IsNullOrWhiteSpace(model.StudentsSerialized))
        {
            model.StudentViewModels = JsonConvert.DeserializeObject<List<StudentVm>>(model.StudentsSerialized);
            model.StudentsSerialized = string.Empty;
        }

        if (!string.IsNullOrWhiteSpace(model.SelectedStudentsSerialized))
        {
            model.SelectedStudents = JsonConvert.DeserializeObject<List<StudentVm>>(model.SelectedStudentsSerialized);
            model.SelectedStudentsSerialized = string.Empty;
        }

        return View(model);
    }

型番

public class CourseVM
{
    public CourseVM()
    {
        this.StudentViewModels = new List<StudentVm>();
        this.SelectedStudents = new List<StudentVm>();
    }

    public int CourseId { get; set; }

    [Required(ErrorMessage = "Course name is required")]
    [StringLength(100, ErrorMessage = "Course name cannot be this long.")]
    public string CourseName { get; set; }

    public List<StudentVm> StudentViewModels { get; set; }
    public List<StudentVm> SelectedStudents { get; set; }

    public string StudentsSerialized { get; set; }
    public string SelectedStudentsSerialized { get; set; }
}

public class StudentVm
{
    public int ID { get; set; }
    public string Name { get; set; }
    public string Lastname { get; set; }
}

CSHTMLページ

@using (Html.BeginForm())
{
    @Html.ValidationSummary(true)
    <fieldset>
        <legend>CourseVM</legend>

        <div>
            <div class="editor-label">
                @Html.LabelFor(model => model.CourseId)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.CourseId, new { data_bind = "enable: isInEditMode, value: CourseId" })
                @Html.ValidationMessageFor(model => model.CourseId)
            </div>

            <div class="editor-label">
                @Html.LabelFor(model => model.CourseName)
            </div>
            <div class="editor-field">
                @Html.TextBoxFor(model => model.CourseName, new { data_bind = "enable: isInEditMode, value: CourseName" })
                @Html.ValidationMessageFor(model => model.CourseName)
            </div>
            <div class="editor-label">
                @Html.LabelFor(model => model.StudentViewModels);
            </div>
            <div class="editor-field">

                @Html.ListBoxFor(
                    model => model.StudentViewModels,
                    new SelectList(this.Model.StudentViewModels, "ID", "Name"),
                    new
                    {
                        style = "width: 37%;",
                        data_bind = "enable: isInEditMode, options: StudentViewModels, optionsText: 'Name', value: leftStudentSelected, event: { dblclick: moveFromLeftToRight }"
                    }
                )
                @Html.ListBoxFor(
                    model => model.SelectedStudents,
                    new SelectList(this.Model.SelectedStudents, "ID", "Name"),
                    new
                    {
                        style = "width: 37%;",
                        data_bind = "enable: isInEditMode, options: SelectedStudents, optionsText: 'Name', value: rightStudentSelected, event: { dblclick: moveFromRightToLeft }"
                    }
                )
            </div>

            @Html.HiddenFor(model => model.CourseId, new { data_bind="value: CourseId" })
            @Html.HiddenFor(model => model.CourseName, new { data_bind="value: CourseName" })
            @Html.HiddenFor(model => model.StudentsSerialized, new { data_bind = "value: StudentsSerialized" })
            @Html.HiddenFor(model => model.SelectedStudentsSerialized, new { data_bind = "value: SelectedStudentsSerialized" })
        </div>

        <p>
            <input type="submit" value="Save" data-bind="enable: !isInEditMode()" /> 
            <button data-bind="enable: !isInEditMode(), click: editMode">Edit mode</button><br />
            <div>
                <button data-bind="enable: isInEditMode, click: addStudent">Add Student</button>
                <button data-bind="enable: hasChanges, click: executeCommit">Commit</button>
                <button data-bind="enable: isInEditMode, click: executeRollback">Cancel</button>
            </div>
        </p>
    </fieldset>
}

スクリプト

<script src="@Url.Content("~/Scripts/jquery-1.7.2.min.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/knockout-2.1.0.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/knockout.mapping-latest.js")" type="text/javascript"></script>
<script src="@Url.Content("~/Scripts/ko.editables.js")" type="text/javascript"></script>

<script type="text/javascript">
    var g = null;
    function ViewModel() {
        this.addStudent = function () {
            this.StudentViewModels.push(new Student(25, "my name" + new Date(), "my last name"));
            this.serializeLists();
        };
        this.serializeLists = function () {
            this.StudentsSerialized(ko.toJSON(this.StudentViewModels));
            this.SelectedStudentsSerialized(ko.toJSON(this.SelectedStudents));
        };
        this.leftStudentSelected = ko.observable();
        this.rightStudentSelected = ko.observable();
        this.moveFromLeftToRight = function () {
            this.SelectedStudents.push(this.leftStudentSelected());
            this.StudentViewModels.remove(this.leftStudentSelected());
            this.serializeLists();
        };
        this.moveFromRightToLeft = function () {
            this.StudentViewModels.push(this.rightStudentSelected());
            this.SelectedStudents.remove(this.rightStudentSelected());
            this.serializeLists();
        };
        this.isInEditMode = ko.observable(false);
        this.executeCommit = function () {
            this.commit();
            this.isInEditMode(false);
        };
        this.executeRollback = function () {
            if (this.hasChanges()) {
                if (confirm("Are you sure you want to discard the changes?")) {
                    this.rollback();
                    this.isInEditMode(false);
                }
            }
            else {
                this.rollback();
                this.isInEditMode(false);
            }
        };
        this.editMode = function () {
            this.isInEditMode(!this.isInEditMode());
            this.beginEdit();
        };
    }

    function Student(id, name, lastName) {
        this.ID = id;
        this.Name = name;
        this.LastName = lastName;
    }

    $(function () {
        var jsonModel = '@Html.Raw(JsonConvert.SerializeObject(this.Model))';
        var mvcModel = ko.mapping.fromJSON(jsonModel);

        var myViewModel = new ViewModel();
        g = ko.mapping.fromJS(myViewModel, mvcModel);

        g.StudentsSerialized(ko.toJSON(g.StudentViewModels));
        g.SelectedStudentsSerialized(ko.toJSON(g.SelectedStudents));

        ko.editable(g);
        ko.applyBindings(g);
    });
</script>

注:以下の行を追加しました:

        @Html.HiddenFor(model => model.CourseId, new { data_bind="value: CourseId" })
        @Html.HiddenFor(model => model.CourseName, new { data_bind="value: CourseName" })

フォームを送信するとフィールドが無効になるため、値がサーバーに送信されなかったため、トリックを実行するためにいくつかの非表示フィールドを追加しました


うーん、非常に有益です。あなたの答えとPualの答えから、私は編集可能なプラグインの使い方を除いて、ほとんどすべての質問に答えられたと思います。うまくいけば、誰かが私がこれをどのように使用できるか知っています。
chobo2

1
ko.editablesプラグインとの互換性を追加しました。更新された応答を確認するか、必要に応じてプロジェクト全体をダウンロードしてローカルで実行できます
Jupaol

できればチェックします。それを機能させるために多くを変更する必要がありましたか?すべてのプラグインについて、変更する必要があり、自分のバージョンを維持する必要があるかどうかを知りたいのですが。
chobo2

いいえ。あなたは驚かれることでしょう、それはほとんどそのままで
Jupaol

1
たくさんの人に感謝し、私はあなたの反応からいくつかの新しい戦略を学びました。賞賛!
sky-dev

23

ASP.NET MVCビューモデルをjavascript変数にシリアル化できます。

@model CourseVM
<script type="text/javascript">
    var model = @Html.Raw(Json.Encode(Model));
    // go ahead and use the model javascript variable to bind with ko
</script>

ノックアウトドキュメントには、多くの例があります。


1
はい、私は彼らがサイトで持っているインタラクティブなチュートリアルを体験しましたが、asp.net mvcと関係があることは本当にありません。マッピングプラグインもいくつかあるようですが、どのように適合するかはわかりません。あなたの例では、(別のスクリプトで)ノックアウトモデルにどのようにバインドしますか?インラインJavaScriptをできるだけ少なくしたいのですが(非推奨ですが、不可能だと思います)
chobo2

2
解決しようとしている問題は何ですか?MVCビューが必要で、それらの使用方法に満足している場合は、そのまま使用できます。クライアント側のデータバインディングと操作が必要な場合は、KOが最適です。この回答が示すように、MVCコードからKOビューモデルを生成できます。これはvmを受け取り、jsonにシリアル化します。次に、クライアントで結果をJavaScriptビューモデルにマッピングできます。次に、viewmodelをビューにバインドすると、すべての準備が整います。重要なのは、MVCとKOは、必要な場合を除いて、いかなる方法でも結合する必要がないことです。そのすべては、解決しようとしている問題に依存しています。
John Papa

1
asp.net mvcとは何の関係もないのは正常なことです。Knockoutはクライアント側のフレームワークです。どのサーバー側の言語を使用しているかはわかりません。これらの2つのフレームワークは完全に分離する必要があります。
Darin Dimitrov

@JohnPapa-私は今のやり方が好きですが、新しいことを学ぶことも好きです(KOはいくつかの状況で非常に役立つことがあります)。私はKOがクライアント側のスクリプトであることを知っていますが、私はそれらが一緒に機能していると考えています。現在、ビューモデルとHTMLヘルパーを使用してビューを生成しています。だから私の心では、KOはこれと連携する必要があります。たとえば、編集ダイアログが表示されたとします。どのように設計して、dbからこれらのフィールドに値を入力しますか。私が自分のやり方で使用している場合は、viewModelを持つhtmlヘルパーのビューになります。ビューモデルにデータを入力し、アクションメソッドを介して送信して使用します。
chobo2

1
@ chobo2、ノックアウトはクライアント側のフレームワークです。クライアントのビューモデルを使用して、クライアントにMVCパターンを実装します。サーバーは分離されています。ビューモデルを使用することもできます。それはちょうど2つの異なる場所です。JavaScriptを使用してクライアントに実装したい複雑なロジックがある場合、ノックアウトはこれを簡略化できます。そうでなければ、正直なところ、それは必要ありません。
Darin Dimitrov

2

サーバーのマッピング後に追加の計算されたプロパティを実現するには、クライアント側のビューモデルをさらに拡張する必要があります。

例えば:

var viewModel = ko.mapping.fromJS(model);

viewModel.capitalizedName = ko.computed(function() {...}, viewModel);

したがって、未加工のJSONからマップするたびに、計算されたプロパティを再適用する必要があります。

さらに、マッピングプラグインは、前後に移動するたびにビューモデルを再作成するのではなく、ビューモデルを段階的に更新する機能を提供します(で追加のパラメーターを使用しますfromJS)。

// Every time data is received from the server:
ko.mapping.fromJS(data, viewModel);

そして、マップされたプロパティのみのモデルで増分データ更新を実行します。詳細については、マッピングのドキュメントをご覧ください。

DarinのFluentJSONパッケージの回答のコメントで言及しました。私はその作成者ですが、その使用例はko.mappingよりも具体的です。私は通常、ビューモデルが一方向(つまり、サーバー->クライアント)で、データが異なる形式で(またはまったく)ポストされない場合にのみ使用します。または、JavaScriptビューモデルをサーバーモデルとは実質的に異なる形式にする必要がある場合。


ふーん、ビューモデルはほとんどの場合双方向になるので、おそらくFluentJSONは私には向かないと思います(通常、jsonを介して送り返してから、アクションメソッドパラメータでビューモデルにバインドします)。私が編集可能と言ったプラグインをどのように使用できるか知っていますか?最後に、マッピングを使用してビューモデルを使用しようとするか、使用しないことで、何らかの機能を失っていますか?
chobo2

私はどのプラグインも使ったことがないのでわからない。私が過去にやったことは、すべての変更をサブスクライブし、変更時にプッシュして元に戻すときにポップするシリアル化されたビューモデルの状態のスタックを保持することでした(この質問を参照)。
Paul Tyng

マッピングによって機能が制限されることはありません。JSへのマッピングとJSからのマッピングを処理するための規則を確認して順守するだけで、すべてがうまく機能するようになります。
Paul Tyng

まあ、あなたが投稿した質問に対する受け入れられた答えは、基本的にプラグインがどうなるかです。ビューモデルを作成し、作成した関数(ko.observableArrayWithUndo([]))を使用しているのを見ると、混乱しています。マッピングを行っている場合、その方法がわかりません。頭に浮かぶのは、元に戻すことができるか、各プロパティをマッピングする独自のマッピング(現時点では正しいとは思えない)を記述することですが、基本的にはサーバー側とクライアント用のビューモデルが重複しています。維持できなくなると怖い
chobo2

ああ、申し訳ありませんが、その質問への私の回答について話していました。申し訳ありませんが、直接リンクする必要がありました。
Paul Tyng
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.