mvvm - How to save VM back to Server with KnockoutJs -


i have asp.net mvc5 app ef 6 on server. site has dozen or pages, each of has grid displaying business data many columns.

certain users not interested in of columns on of pages (views) need way them indicate views make visible.

on database, view has many columns , user can designate column of view displayed (and stored in userviewcolumn table):

enter image description here

i using following viewmodel pass data selected database view:

public class userprefsviewmodel     {         public icollection<vmuser> users { get; set; }          public userprefsviewmodel()         {             this.users = new list<vmuser>();         }     }      public class vmuser     {         public int userid { get; set; }         public string adlogondomain { get; set; }         public string adlogonid { get; set; }         public list<vmview> views { get; set; }     }      public class vmview     {         public int viewid { get; set; }         public string name { get; set; }         public list<vmcolumn> allcolumns { get; set; }         public list<vmcolumn> visiblecolumns { get; set; }     }      public class vmcolumn     {         public int columnid { get; set; }         public string heading { get; set; }     } 

the razor view follows:

@model tvs.esb.bamportal.website.models.userprefsviewmodel @using system.web.script.serialization @{     viewbag.title = "user preferences";     layout = "~/views/shared/_layout.cshtml"; }  <h2>@viewbag.title</h2> @{  string data = new javascriptserializer().serialize(model); }  <div id="viewsandcolumns" class="container">     <div class="row">         <div id="views" class="col-md-3 pull-left">             <span class="label-info">views</span>             <br />             <table>                 <tr>                     <td>                         <select style="width:100px" size="5" data-bind="options:views, optionstext: 'name', value:selectedview"> </select>                     </td>                 </tr>             </table>         </div>         <div id="columns" class="col-md-9 pull-right">             <table>                 <tr>                     <td>                         <span class="label-info">available columns</span>                     </td>                     <td>                         <span class="label-info">to display</span>                     </td>                 </tr>                 <tr>                     <td>                         <select size="10" data-bind="options:allcolumns, optionstext: 'heading', value:selectedavailablecolumn"></select>                     </td>                     <td>                         <select size="10" data-bind="options:columnstoadd, optionstext: 'heading', value:selectedcolumntoremove"></select>                     </td>                 </tr>                 <tr>                     <td>                         <button class="btn-default" data-bind="click:addcolumn">add</button>                     </td>                     <td>                         <button class="btn-default" data-bind="click:removecolumn">remove</button>                     </td>                 </tr>                 <tr>                     <td>                         <button class="btn-danger" data-bind="click:savetodatabase.bind($data, '@viewbag.domain', '@viewbag.loginid')">save database</button>                     </td>                 </tr>             </table>         </div>     </div> </div>    @section scripts {     <script src="~/knockoutvm/userprefs.js"></script>      <script type="text/javascript">         var vm = new viewmodel(@html.raw(data));         ko.applybindings(vm, document.getelementbyid("userprefsdiv"));     </script> } 

here's screen grab:

enter image description here

i using knockoutjs enable user add columns first select list second, here knockout file:

function viewmodel(data) {     var self = this;     var viewcolumns;     var visibleviewcolumns      self.selectedavailablecolumn = ko.observable();     self.selectedview = ko.observable(data.users[0].views[0]);     self.views = ko.observablearray(data.users[0].views);     self.selectedavailablecolumn = ko.observable();     self.columnstoadd = ko.observablearray();     self.selectedcolumntoremove = ko.observable();      var getbyid = function (items, id) {         return ko.utils.arrayfirst(items(), function (item) {             return item.viewid == id;         });     };      self.allcolumns = ko.computed(function () {         var view = getbyid(self.views, self.selectedview().viewid);         return view ? ko.utils.arraymap(view.allcolumns, function (item) {             return {                 columnid: item.id,                 heading: item.heading             };         }) : [];     }, this);      self.addcolumn = function () {         if (self.columnstoadd().indexof(self.selectedavailablecolumn()) < 0) {             self.columnstoadd.push(self.selectedavailablecolumn());         }     };      self.removecolumn = function () {         self.columnstoadd.remove(self.selectedcolumntoremove());     };      self.savetodatabase = function () {         var jssavemodel = ko.tojs(data);          $.ajax({             type: "post",             url: location.href,             data: ko.tojson(jssavemodel),             contenttype: 'application/json',             async: true         });     }; }; 

my problem is, don't know how best manage knockout view model before posting server persist database. can see, load data server vm observable arrays bound view controls. in server side vm, user[x].views[y].visiblecolumns collection use populate userviewcolumn table, identifying columns user wishes display.

i guess 1 way change data param knockout viewmodel receives. in self.savetodatabase function before posting data server? since have little experience of knockout or mvvm framework, i'd appreciate advice on best practice.

this flagged being broad , opinion-based, use ajax. while require second round-trip server results in minimal display time , can show spinner or while retrieving data itself. it's more flexible in allows more host content on 1 machine , data on another, becomes important down track user-base increases , hosting solution needs balance traffic across multiple servers.

in case here's idea of ajax handlers server-side:

    public class model     {         public string data { get; set; }     }      [httpget]     public jsonresult getmodel(/* can use params here if required */)     {         var model = new model { data = "some data" };         return json(model, jsonrequestbehavior.allowget);     }      [httppost]     public jsonresult postmodel(model model)     {         var result = new { status = "success"};         return json(result);     } 

and client-side:

    getmodel: function () {         var self = this;         $.ajax({             url: "/getmodel",             method: "get",             datatype: "json",             success: function (model) {                 // model here , let's post server                 self.postmodel(model);             },             fail: function () {                 alert("failed retrieve model");             },             cache: false         });     },      postmodel: function (model) {         var self = this;         $.ajax({             url: "/postmodel",             method: "post",             data: model,             datatype: "json",             success: function (status) {                 alert("submitted!");             },             fail: function () {                 alert("failed post model");             },             cache: false         });     } 

what typically need create view model data, the knockout site has more details how that.


Comments

Popular posts from this blog

gridview - Yii2 DataPorivider $totalSum for a column -

java - Suppress Jboss version details from HTTP error response -

Sass watch command compiles .scss files before full sftp upload -