Bagaimana cara menggunakan knockout.js dengan ASP.NET MVC ViewModels?

129

Karunia

Sudah beberapa saat dan saya masih memiliki beberapa pertanyaan luar biasa. Saya berharap dengan menambahkan hadiah mungkin pertanyaan-pertanyaan ini akan dijawab.

  1. Bagaimana Anda menggunakan html helpers dengan knockout.js
  2. Mengapa dokumen siap diperlukan untuk membuatnya berfungsi (lihat edit pertama untuk informasi lebih lanjut)

  3. Bagaimana saya melakukan sesuatu seperti ini jika saya menggunakan pemetaan sistem gugur dengan model tampilan saya? Karena saya tidak memiliki fungsi karena pemetaan.

    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. Saya ingin menggunakan plugin misalnya saya ingin dapat mengembalikan yang dapat diamati seolah-olah pengguna membatalkan permintaan saya ingin dapat kembali ke nilai terakhir. Dari penelitian saya ini tampaknya dapat dicapai oleh orang yang membuat plugin seperti yang dapat diedit

    Bagaimana saya menggunakan sesuatu seperti itu jika saya menggunakan pemetaan? Saya benar-benar tidak ingin pergi ke metode di mana saya miliki dalam pemetaan manual tampilan saya adalah saya memetakan setiap bidang viewMode MVC ke bidang model KO karena saya ingin sesedikit mungkin javascript sebaris mungkin dan yang sepertinya menggandakan pekerjaan dan itu mengapa saya suka pemetaan itu.

  5. Saya khawatir untuk membuat pekerjaan ini mudah (dengan menggunakan pemetaan) saya akan kehilangan banyak daya KO tetapi di sisi lain saya khawatir bahwa pemetaan manual hanya akan banyak pekerjaan dan akan membuat pandangan saya mengandung terlalu banyak informasi dan mungkin menjadi lebih sulit di masa depan untuk mempertahankan (katakanlah jika saya menghapus properti dalam model MVC saya harus memindahkannya juga di model tampilan KO)


Pos Asli

Saya menggunakan asp.net mvc 3 dan saya melihat ke sistem gugur karena terlihat cukup keren tapi saya mengalami kesulitan mencari tahu cara kerjanya dengan asp.net mvc terutama melihat model.

Bagi saya sekarang saya melakukan sesuatu seperti ini

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

}

Saya akan memiliki Vm yang memiliki beberapa properti dasar seperti CourseName dan akan memiliki beberapa validasi sederhana di atasnya. Model Vm mungkin berisi model tampilan lain di dalamnya juga jika diperlukan.

Saya kemudian akan meneruskan Vm ini ke Tampilan jika saya akan menggunakan html helpers untuk membantu saya menampilkannya kepada pengguna.

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

Saya mungkin memiliki beberapa loop foreach atau sesuatu untuk mendapatkan data dari koleksi Model Student View.

Lalu ketika saya akan mengirimkan formulir saya akan menggunakan jquery dan serialize array dan mengirimkannya ke metode tindakan pengontrol yang akan mengikatnya kembali ke model view.

Dengan knockout.js semuanya berbeda karena Anda sekarang punya viewmodels untuk itu dan dari semua contoh yang saya lihat mereka tidak menggunakan html helpers.

Bagaimana Anda menggunakan 2 fitur MVC ini dengan knockout.js?

Saya menemukan video ini dan secara singkat (beberapa menit terakhir dari video @ 18:48) masuk ke cara untuk menggunakan viewmodels dengan pada dasarnya memiliki skrip inline yang memiliki viewmodel knockout.js yang mendapatkan nilai-nilai dalam ViewModel.

Apakah ini satu-satunya cara untuk melakukannya? Bagaimana kalau dalam contoh saya dengan memiliki koleksi viewmodels di dalamnya? Apakah saya harus memiliki loop foreach atau sesuatu untuk mengekstrak semua nilai keluar dan menetapkannya ke sistem gugur?

Adapun pembantu html video tidak mengatakan apa-apa tentang mereka.

Ini adalah 2 area yang membingungkan saya karena tidak banyak orang yang membicarakannya dan membuat saya bingung bagaimana nilai awal dan semuanya terlihat saat contoh hanya beberapa contoh nilai hard-coded.


Edit

Saya mencoba apa yang disarankan Darin Dimitrov dan ini tampaknya berhasil (saya harus membuat beberapa perubahan pada kodenya). Tidak yakin mengapa saya harus menggunakan dokumen siap tetapi entah bagaimana semuanya tidak siap tanpanya.

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

Saya harus membungkusnya di sekitar dokumen jquery yang siap untuk membuatnya berfungsi.

Saya juga mendapat peringatan ini. Tidak yakin tentang apa semua ini.

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

Jadi saya punya titik awal, saya kira setidaknya akan memperbarui ketika saya melakukan lebih banyak bermain-main dan bagaimana ini bekerja.

Saya mencoba melalui tutorial interaktif tetapi menggunakan ViewModel sebagai gantinya.

Belum yakin bagaimana cara mengatasi bagian-bagian ini

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

atau

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


Edit 2

Saya sudah bisa mencari tahu masalah pertama. Tidak ada petunjuk tentang masalah kedua. Namun demikian. Ada yang punya ide?

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

Pengendali

  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);
    }
chobo2
sumber
2
Saya baru saja menulis posting blog untuk menjawab pertanyaan serupa lainnya: roysvork.wordpress.com/2012/12/09/… Mungkin tidak menjawab pertanyaan Anda sepenuhnya, tetapi memberi Anda ide yang bagus tentang bagaimana hal-hal bisa bekerja. Saya berharap untuk menindaklanjuti ini dengan posting selanjutnya di masa depan yang tidak terlalu jauh. Jangan ragu untuk bertanya kepada saya pertanyaan di komentar di posting atau di sini jika Anda memerlukan informasi lebih lanjut.
luar kode

Jawaban:

180

Saya pikir saya telah merangkum semua pertanyaan Anda, jika saya melewatkan sesuatu tolong beri tahu saya ( Jika Anda bisa meringkas semua pertanyaan Anda di satu tempat akan menyenangkan =))

Catatan. Kompatibilitas dengan ko.editableplug-in ditambahkan

Unduh kode lengkap

Bagaimana Anda menggunakan html helpers dengan knockout.js

Ini mudah:

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

Dimana:

  • value: CourseIdmenunjukkan bahwa Anda mengikat valueproperti inputkontrol dengan CourseIdproperti dari model dan model skrip Anda

Hasilnya adalah:

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

Mengapa dokumen siap diperlukan untuk membuatnya berfungsi (lihat edit pertama untuk informasi lebih lanjut)

Saya belum mengerti mengapa Anda perlu menggunakan readyacara tersebut untuk membuat serial model, tetapi tampaknya itu hanya diperlukan (meskipun tidak perlu khawatir tentang hal itu)

Bagaimana saya melakukan sesuatu seperti ini jika saya menggunakan pemetaan sistem gugur dengan model tampilan saya? Karena saya tidak memiliki fungsi karena pemetaan.

Jika saya mengerti dengan benar Anda perlu menambahkan metode baru ke model KO, yah itu model penggabungan yang mudah

Untuk info lebih lanjut, di bagian -Petakan dari berbagai sumber-

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);
});

Tentang peringatan yang Anda terima

Peringatan 1 Kompilasi bersyarat dimatikan -> @ Html.Raw

Anda perlu menggunakan kutipan

Kompatibilitas dengan plug-in ko.editable

Saya pikir itu akan menjadi lebih kompleks, tetapi ternyata integrasi sangat mudah, untuk membuat model Anda dapat diedit, tambahkan saja baris berikut: (ingat bahwa dalam hal ini saya menggunakan model campuran, dari server dan menambahkan ekstensi di klien dan dapat diedit hanya berfungsi ... hebat):

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

Dari sini Anda hanya perlu bermain dengan binding menggunakan ekstensi yang ditambahkan oleh plug-in, misalnya, saya memiliki tombol untuk mulai mengedit bidang saya seperti ini dan pada tombol ini saya memulai proses edit:

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

Kemudian saya telah melakukan dan membatalkan tombol dengan kode berikut:

    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);
        }
    };

Dan akhirnya, saya memiliki satu bidang untuk menunjukkan apakah bidang dalam mode edit atau tidak, ini hanya untuk mengikat properti yang diaktifkan.

this.isInEditMode = ko.observable(false);

Tentang pertanyaan array Anda

Saya mungkin memiliki beberapa loop foreach atau sesuatu untuk mendapatkan data dari koleksi Model Student View.

Kemudian ketika saya akan mengirimkan formulir saya akan menggunakan jquery dan serialize array dan mengirimkannya ke metode aksi pengontrol yang akan mengikatnya kembali ke viewmodel.

Anda dapat melakukan hal yang sama dengan KO, dalam contoh berikut, saya akan membuat output berikut:

masukkan deskripsi gambar di sini

Pada dasarnya di sini, Anda memiliki dua daftar, dibuat menggunakan Helpersdan diikat dengan KO, mereka memiliki dblClickacara yang diikat ketika dipecat, menghapus item yang dipilih dari daftar saat ini dan menambahkannya ke daftar lain, ketika Anda memposting ke Controller, konten masing-masing daftar dikirim sebagai data JSON dan dilampirkan kembali ke model server

Nugget:

Skrip eksternal .

Kode pengontrol

    [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);
    }

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

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

Skrip

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

Catatan: Saya baru saja menambahkan baris ini:

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

Karena ketika saya mengirimkan formulir, bidang saya dinonaktifkan, sehingga nilai tidak dikirim ke server, itu sebabnya saya menambahkan beberapa bidang tersembunyi untuk melakukan trik

Jupaol
sumber
Hmm sangat informatif. Dari jawaban Anda dan jawaban Pual saya pikir saya hampir mendapatkan semua pertanyaan saya dijawab kecuali bagaimana menggunakan plugin seperti yang dapat diedit. Semoga ada yang tahu bagaimana saya bisa menggunakan ini.
chobo2
1
Saya baru saja menambahkan kompatibilitas dengan ko.editablesplug-in, Anda dapat memeriksa respons yang diperbarui atau jika Anda mau, Anda dapat mengunduh seluruh proyek untuk menjalankannya secara lokal
Jupaol
Saya akan memeriksanya ketika saya bisa. Apakah banyak yang harus diubah untuk membuatnya bekerja? Saya bertanya-tanya apakah untuk setiap plugin saya menemukan apakah saya harus mengubahnya dan kemudian harus mempertahankan versi saya sendiri.
chobo2
Nggak. Anda akan terkejut, itu hampir out-of-the-box
Jupaol
1
Terima kasih banyak, saya belajar beberapa strategi baru dari respons Anda. Pujian!
sky-dev
23

Anda bisa membuat serial model ASP.NET MVC Anda menjadi variabel 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>

Ada banyak contoh dalam dokumentasi KO yang bisa Anda lalui.

Darin Dimitrov
sumber
1
Ya, saya telah melalui tutorial interaktif yang mereka miliki di situs tetapi saya benar-benar tidak pernah melihat ada hubungannya dengan asp.net mvc. Saya melihat mereka juga memiliki beberapa plugin pemetaan tetapi tidak yakin bagaimana itu cocok. Dalam contoh Anda bagaimana Anda akan mengikatnya ke model sistem gugur (dalam skrip lain). Saya benar-benar ingin memiliki sesedikit mungkin javascript sebaris mungkin (non lebih disukai tetapi saya kira tidak mungkin)
chobo2
2
Masalah apa yang Anda coba selesaikan? Jika Anda ingin tampilan MVC dan senang dengan cara menggunakannya, Anda bisa tetap di sana. Jika Anda ingin pengikatan dan manipulasi data sisi klien, maka KO adalah pilihan yang bagus. Anda dapat membuat model tampilan KO dari kode MVC Anda seperti yang ditunjukkan oleh jawaban ini. Dibutuhkan vm dan cerita bersambung ke json. Kemudian pada klien Anda dapat memetakan hasilnya ke model tampilan javascript. Kemudian ikat model view ke tampilan dan Anda siap. Kuncinya adalah bahwa MVC dan KO tidak harus digabungkan dengan cara apa pun, kecuali jika Anda menginginkannya. Semuanya tergantung pada masalah yang Anda coba selesaikan.
John Papa
1
Itu normal bahwa Anda tidak melihat ada hubungannya dengan asp.net mvc. Knockout adalah kerangka kerja sisi klien. Tidak tahu juga tidak peduli apa bahasa sisi server yang Anda gunakan. 2 kerangka kerja tersebut harus benar-benar dipisahkan.
Darin Dimitrov
@ JohnPapa - Saya suka cara saya melakukan hal-hal sekarang tetapi saya juga suka belajar hal-hal baru (saya melihat bahwa KO bisa sangat berguna dalam beberapa situasi). Saya tahu KO adalah skrip sisi klien tetapi bagi saya saya melihat mereka bekerja bersama. Saat ini saya menghasilkan pandangan saya menggunakan model tampilan dan bantuan html. Jadi dalam pikiran saya KO perlu bekerja sama dengan ini. Misalnya katakan Anda mendapat dialog edit. Bagaimana Anda mendesain dan mengisi nilai-nilai dari db ke dalam bidang tersebut. Jika saya menggunakan cara saya, itu akan menjadi tampilan html helpers yang memiliki viewModel. Akan mengisi viewmodel dan mengirimkannya melalui Metode Tindakan dan menggunakannya.
chobo2
1
@ chobo2, sistem gugur adalah kerangka kerja sisi klien. Ini menggunakan model tampilan pada klien untuk menerapkan pola MVC pada klien. Server dipisahkan. Anda juga dapat menggunakan model tampilan di atasnya. Hanya ada 2 tempat berbeda. Jika Anda memiliki beberapa logika kompleks yang ingin Anda terapkan pada klien menggunakan javascript maka sistem gugur dapat menyederhanakan ini. Kalau tidak, jujur, Anda tidak membutuhkannya.
Darin Dimitrov
2

Untuk mencapai properti yang dihitung tambahan setelah pemetaan server, Anda perlu lebih meningkatkan model tampilan Anda di sisi klien.

Sebagai contoh:

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

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

Jadi, setiap kali Anda memetakan dari JSON mentah, Anda harus menerapkan kembali properti yang dihitung.

Selain itu, plugin pemetaan menyediakan kemampuan untuk memperbarui model tampilan secara bertahap daripada membuatnya kembali setiap kali Anda bolak-balik (gunakan parameter tambahan di fromJS):

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

Dan itu mengeksekusi pembaruan data tambahan pada model Anda hanya properti yang dipetakan. Anda dapat membaca lebih lanjut tentang itu di dokumentasi pemetaan

Anda menyebutkan dalam komentar tentang jawaban Darwin paket FluentJSON . Saya penulisnya, tetapi use case-nya lebih spesifik daripada pemetaan ko. Saya biasanya hanya akan menggunakannya jika viewmodels Anda satu arah (mis. Server -> client) dan kemudian data diposting kembali dalam beberapa format yang berbeda (atau tidak sama sekali). Atau jika model tampilan javascript Anda harus dalam format yang jauh berbeda dari model server Anda.

Paul Tyng
sumber
Hmm maka saya kira mungkin FluentJSON bukan untuk saya sebagai viewmodels saya sebagian besar waktu berjalan dua arah (saya biasanya mengirimnya kembali melalui json dan kemudian mengikatnya ke viewmodel dalam parameter metode tindakan). Apakah Anda tahu bagaimana saya bisa menggunakan plugin yang saya sebutkan suka diedit? Akhirnya apakah saya kehilangan fungsionalitas apa pun dengan menggunakan pemetaan dan mencoba menggunakan viewmodel vs saya tidak menggunakannya?
chobo2
Saya belum pernah menggunakan plugin itu jadi tidak yakin. Apa yang telah saya lakukan di masa lalu adalah hanya berlangganan setiap perubahan dan menyimpan setumpuk tampilan viewmodel berseri yang saya akan mendorong untuk perubahan dan pop pada membatalkan ( lihat pertanyaan ini ).
Paul Tyng
pemetaan tidak menjauhkan Anda dari fungsionalitas apa pun, Anda hanya perlu memastikan dan mengamati konvensi-konvensi untuk bagaimana menangani pemetaan ke dan dari JS untuk menjadikan semuanya bermain dengan baik bersama.
Paul Tyng
Yah jawaban yang diterima untuk pertanyaan yang Anda posting pada dasarnya adalah apa plugin itu. Itulah yang membingungkan saya karena Anda dapat melihat mereka membuat viewmodel dan kemudian menggunakan fungsi yang mereka buat (ko.observableArrayWithUndo ([])). Jika saya melakukan pemetaan, saya tidak tahu bagaimana melakukannya. Satu-satunya hal yang terlintas dalam pikiran adalah menulis pemetaan saya sendiri (apa yang saya ragu saya bisa benar saat ini) yang telah membatalkan diamati atau memetakan setiap properti keluar tapi kemudian saya pada dasarnya memiliki duplikat viewmodels satu untuk sisi server dan satu untuk klien dan saya takut itu akan menjadi tidak dapat dipelihara
chobo2
Ah ya maaf saya sedang berbicara tentang jawaban saya untuk pertanyaan itu, maaf seharusnya terhubung langsung.
Paul Tyng