Pertanyaan bentuk bangunan dinamis dengan knockoutjs


Saya perlu membangun bentuk dinamis dari basis data. Saya telah mengikuti Entitas untuk menentukan kolom formulir dengan cepat:

    public class FormField {
        public int ID { get; set; }
        public string Name { get; set; }
        public string Type { get; set; }    // Possible values are: 'Radio','Combo','Text'. A dropdown will be created for a Combo type of element, a radio set for Radio type of element and a text input for Text type of element.
        public string Options { get; set; } // Only relevant in case of Radio/Combo type
        public string Default { get; set; } // Default value in case of Type 'Text' and selected value in case of Type 'Radio/Combo'
        public string Blankout { get; set; }// An expression to define when this field should be hidden 
    }

    /* A sample JSON array (from the DB) to build the form would be:
       [
        { Name:"Gender", Type:"radio", Options:["Male","Female","Unknown"], Default:"Male", Blankout:"Never" },
        { Name:"Age", Type:"text", Options:"None", Default:15, Blankout:"Never" },
        { Name:"Neighbourhood", Type:"Combo", Options:["Eastern","Western","Northern","Southern","Central"], Default:"Central", Blankout:"if (Age < 40 or Voted='Obama')" },
        { Name:"Voted", Type:"Combo", Options:["Obama","Romney","Harry Potter"], Default:"Harry Potter", Blankout:"if ((Gender='Female' and Age < 15) or Neighbourhood='Eastern'" }
       ]
    */

Saya dapat membangun bentuk dinamis dari catatan 'FormField' di DB, TAPI masalahnya adalah saya harus melacak perubahan nilai dari setiap kolom formulir, dan ketika perubahan nilai terjadi saya harus mengirim semua data formulir ke server ( asynchronous) untuk mengevaluasi rumus 'Blankout' pada Server. Jika saya melakukan hal pelacakan perubahan ini tanpa KnockoutJS yang tidak responsif dan menjadi sangat sangat kompleks. Saya telah melalui beberapa tutorial KnockoutJS, tetapi tidak dapat mengetahui cara mengatur ViewModel saya untuk masalah khusus ini.

Bantuan apa pun akan dihargai.

Perbarui 1

Saya telah mencoba mengirim data formulir ini ke pengontrol dengan menggunakan kode berikut:

    $.ajax({
            type: "POST",
            url: "/MyController/GetBlankoutElements",
            contentType: 'application/json',
            dataType: 'json',
            data: JSON.stringify(ko.toJSON(self)),
            success: function(result) {
                alert(result);
                //self.HiddenElements(result.split(','));
            }
    });

Di controller saya, saya telah mencoba kode berikut:

    [HttpPost]
    public ActionResult GetBlankoutElements(List<MyFieldViewModel> Fields)
    {
        return Json(Fields); // List, Fields is null here
    }

Dia adalah apa yang tampak seperti kelas MyFieldViewModel:

    public class MyFieldViewModel 
    {
        public string Title { get; set; }
        public string Name { get; set; }
        public string Type { get; set; }
        public string Default { get; set; }
        public string[] Options { get; set; }
    }

Saya telah mencoba kiat yang dijelaskan di Posting Array Objek melalui JSON ke ASP.Net MVC3

Berikut ini adalah data Json yang dicetak ketika saya mengeksekusi alert (ko.toJSON (self))

    {"Fields":
        [{"Title":"CCType","Name":"CCType","Type":"Radio","Default":"Enterprise","Options":["Enterprise","Express","CVP","PCCE"]},{"Title":"Industry","Name":"Industry","Type":"Combo","Default":"Banks","Options":["Banks","ServiceProvider","Outsourcer","Airlines","Utilities","Government","Retail"]},{"Title":"Customer Lab","Name":"CustomerLab","Type":"Combo","Default":"0","Options":["0","1"]},{"Title":"No of Agents","Name":"Agents","Type":"Text","Default":"if(c.CCType==\"CVP\") then 10 else 25","Options":[]},{"Title":"ExpLicType","Name":"ExpLicType","Type":"Radio","Default":"if(c.CCType==\"Express\") then \"Enhanced\" else \"None\"","Options":["None","Premium","Standard","Enhanced"]},{"Title":"Multimedia","Name":"Multimedia","Type":"Combo","Default":"WIM","Options":["None","EIM","WIM","EIM&WIM","BSMediaRouting","MCAL"]}],
     "HiddenElements":[]
    }

Yang saya butuhkan hanyalah nama field dan nilai yang dipilih oleh pengguna, dan saya bingung bahkan jika saya mendapatkan data json ini dipetakan ke saya MyFieldViewModel kelas, masih bagaimana saya mendapatkan NILAI yang dipilih?

Perbarui 2  (Pemetaan Data JSON bekerja)

Ketika saya berubah

    data: JSON.stringify(ko.toJSON(self))

dengan         data: ko.toJSON (diri)

Pemetaan bekerja dengan sempurna pada pengontrol saya, seperti yang dapat Anda lihat di tangkapan layar berikut: Debug screenshot of Mapped list object from post json data

Sekarang, masalahnya tetap, seluruh titik pengeposan formulir adalah untuk memperbarui server dengan masukan pengguna pada formulir yaitu nilai terhadap setiap elemen bidang formulir. Bagaimana cara mengirim nilai bidang formulir yang dipilih / diketik saat ini? Sebagai contoh, dalam screenshot di atas, saya dapat melihat Default tetapi bukan nilai yang dipilih saat ini.


5
2017-10-30 12:15


asal


Jawaban:


Untuk melacak perubahan yang dapat Anda gunakan dirty flag dari artikel ini: http://www.knockmeout.net/2011/05/creating-smart-dirty-flag-in-knockoutjs.html.

Buat model tampilan berikut:

function FormField(data) {
    var self = this;

    self.Name = ko.observable(data.Name);
    self.Type = ko.observable(data.Type);
    self.Options = ko.observableArray(data.Type != 'text' ? data.Options : []);
    self.Default = ko.observable(data.Default);
}

function ViewModel(data) {
    var self = this;

    self.Fields = ko.observableArray(ko.utils.arrayMap(data, function(item) {
        return new FormField(item);
    }));

    self.dirtyFlag = new ko.dirtyFlag(this);

    self.isDirty = ko.computed(function (){
        if (self.dirtyFlag.isDirty())
        {
            alert("Value changed!");
            // Do async update.
        }
    });
}

Markup Html:

<div data-bind="foreach: Fields">
    <b data-bind="text: Name"></b>
    <!--ko if: Type() == "combo"-->
        <select data-bind="options: Options, value: Default"></select>                 <!--/ko-->
    <!--ko if: Type() == "radio"-->
        <div data-bind="foreach: Options">
            <input type="radio" value="cherry" data-bind="value: $data, checked: $parent.Default" />
            <span data-bind="text: $data"></span>
        </div>
    <!--/ko-->    
    <!--ko if: Type() == "text"-->
        <input type="text" data-bind="value: Default"></input>                 
    <!--/ko-->   
    <br/>    
</div>

Berikut ini biola kerja: http://jsfiddle.net/vyshniakov/CWTTR/

EDIT:

Berikut adalah jawaban atas pertanyaan Anda jika saya memahaminya dengan benar:

Untuk memposting semua bidang ke server yang dapat Anda gunakan ko.toJSON(self) fungsi. Panggilan ajax Anda akan terlihat sebagai berikut:

    $.ajax({
        type: "POST",
        url: "controller/action",
        contentType: 'application/json',
        data: JSON.stringify(ko.toJSON(self)),
        success: function(result) {
            self.HiddenElements(result);
        }
    });

Lihatlah biola yang diperbarui untuk melihat bagaimana menyembunyikan beberapa bidang tergantung pada respons dari server: http://jsfiddle.net/vyshniakov/CWTTR/1/.


8
2017-10-30 12:54