javascript - Generate and track same template multiple times using Knockout in MVC view? -
i put contacts prototype mvc application uses knockoutjs. i'm new knockout , wondering if design correct in reaching end goal. end goal take mvc model passed contacts view start , achieve following:
- mapping ko viewmodel.
- use bootstrap modal popup input contact data.
- upon clicking add in bootstrap modal call template after posting json data controller , have display under
- edit button on each template rendered under div if clicked brings same modal popup edit templates data.
here's code breakdown of have in place.
view code
<h2>contacts list</h2> <div class="row"> <div class="col-lg-2"></div> <div class="col-lg-10"><h3>ko results</h3></div> </div> <br /> <div class="row"> <div class="col-lg-2"></div> <div class="col-lg-10"><div id="koresults" data-bind="template: { name: 'contactsectiontmp', foreach:contacts }"></div></div> </div> <div class="row"> <div class="col-lg-2"></div> <div class="col-lg-10"><a href="#" id="addcontact" class="btn btn-sm btn-success" data-toggle="modal" data-target="#contactmodal" data-bind="click: addcontact"><strong>add</strong></a></div> </div> @*i enter data in bootstrap modal shown below , when click "add" template below appears in div element koresults data entered. desired effect i'm looking for. *@ <div class="modal" id="contactmodal" tabindex="-1" role="dialog" aria-hidden="true"> <div class="modal-dialog"> <div class="modal-content"> <div class="modal-header" style="background-color:#b8e28d; border-color: black"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">×</button> <h4 class="modal-title" id="mymodallabel">add contact</h4> </div> <div class="form-horizontal"> <form id="contactmodalform" data-bind="with:newcontact,submit:add"> <div class="modal-body"> <h4>contact</h4> <div class="form-group"> <label class="col-sm-4 control-label">name:</label> <div class="col-sm-8"> <input type="text" name="name" class="form-control" data-bind="value: name" /> </div> </div> <div class="form-group"> <label class="col-sm-4 control-label">address:</label> <div class="col-sm-8"> <textarea rows="4" cols="50" name="address" class="form-control" data-bind="value: address"></textarea> </div> </div> <div class="form-group"> <label class="col-sm-4 control-label">phone:</label> <div class="col-sm-8"> <input type="text" name="phone" class="form-control" data-bind="value: phone" /> </div> </div> </div> <div class="modal-footer"> <button type="submit" id="formsubmitcontact" class="btn btn-success">add</button> <button class="btn" data-dismiss="modal" aria-hidden="true">cancel</button> </div> </form> </div> </div> </div> </div> @section scripts <script type="text/javascript" src="~/scripts/knockout-3.4.0.debug.js"></script> <script type="text/javascript" src="~/scripts/knockout.mapping-latest.debug.js"></script> @* knockout template *@ <script id="contactsectiontmp" type="text/html"> <div class="row"> <div class="col-lg-3">name:</div> <div class="col-lg-9" data-bind="text: name"></div> </div> <div class="row"> <div class="col-lg-3">address:</div> <div class="col-lg-9" data-bind="text: address"></div> </div> <div class="row"> <div class="col-lg-3">phone:</div> <div class="col-lg-9" data-bind="text: phone"></div> </div> </script> end section
controller code
pass in model view here. public actionresult contactslist() { contactsvm mdata = new contactsvm(); mdata.contacts = new list<contact>(){ new contact { id = 1, name="drew lucacca", address="782 select st.", phone="421-821-9101"}, new contact {id = 2, name="kevin rosassa", address = "222 potter lane", phone="421-982-5222" }, new contact {id = 3, name="tim kropp", address = "440 ppg place", phone="725-434-8989"} }; return view(mdata); } [httppost] public actionresult contactcreate(contact newcontact) { var res = newcontact; contactsvm mycontacts = new contactsvm(); mycontacts.contacts = new list<contact>(); mycontacts.contacts.add(new contact { id = 4, name = "santa claus", address = "440 trump plaza", phone = "774-489-8989" }); return json(mycontacts); }
javascript code
` //main viewmodel function contactsvm(data) { var self = this; var mapping = { 'contacts': { create: function(options) { return new contact(options.data); } } }; ko.mapping.fromjs(data, mapping, self); self.newcontact = ko.observable(); self.addcontact = function() { debugger; self.newcontact(new contact({name: '', address: '', phone: ''})); } self.add = function () { debugger; var jsdata = data; var jsdata1 = ko.mapping.tojson(self.newcontact()); $.ajax({ url: '@url.action("contactcreate", "home")', type: 'post', data: ko.mapping.tojson(self.newcontact()), datatype: 'json', contenttype: 'application/json; charset=utf-8', success: function (jsonobject) { self.contacts.push(new contact(jsonobject)); } }); // close modal. $('#contactmodal').modal('toggle'); }; self.cancel = function () { // close modal. $('#contactmodal').modal('toggle'); }; //self.resetform = function (formid) { // var form = $('#' + formid); // form.validate().resetform(); // form.get(0).reset(); //}; }; function contact(data) { ko.mapping.fromjs(data, {}, this); this.isedit = ko.observable(false); }; $(function () { var jsonmodel = @html.raw(newtonsoft.json.jsonconvert.serializeobject(this.model)); var vm = new contactsvm(jsonmodel); ko.applybindings(vm); });
contact entity
public class contact { public int id { get; set; } public string name { get; set; } public string address { get; set; } public string phone { get; set; } }
contactsvm entity
public class contactsvm { public list<contact> contacts { get; set; } }
edit #1 see here's thing know javascript isn't correct , note in javascript comments asking if can me identify if isn't correct how should be.
i moved code new location @ bottom of mvc view javascript code didn't seem find model.
javascript - knockout - mapping error
javascript runtime error: 'push' undefined
self.contacts.push(new contact(jsonobject)); < --- error happens here.
any here appreciated , i'm sure others well.
i think might best take iterative approach @ getting working, based on steps have listed. 1 thing @ time, working, move on next item. trying work out @ once , test altogether tough.
first recommendation: make client-side models reflect server-side models. after that, things easier. since using ko mapping, client-side model setup gets easier:
function contactsvm(data) { var mapping = { 'contacts': { create: function(options) { return new contact(options.data); } } }; ko.mapping.fromjs(data, mapping, this); this.newcontact = ko.observable(); } function contact(data) { ko.mapping.fromjs(data, {}, this); this.isedit = ko.observable(false); }
then can create , apply top-level view model well:
var vm = new contactsvm(jsonmodel); ko.applybindings(vm);
this gives top-level viewmodel filled contacts observable array property. can use newcontact property modal add new contact, fill new contact instance.
new contact({name:'', address:'', phone:''})
when push new contact array of contacts, dom automatically update display new contact, won't need use "ko.rendertemplate" logic specified. imagine show/hide modal based on if observable has value if wanted to.
second recommendation: try doing things knockout first, , if can't use jquery. not recommend using jquery serialize form values. remember, have direct access client-side models, no longer dependent upon dom. ko mapping plugin has method unmap regular js object.
Comments
Post a Comment