We use cookies to give you the best experience on our website. If you continue to browse, then you agree to our privacy policy and cookie policy. Image for the cookie policy date
close icon

Knockoutjs_Succintly: Mapping data to viewmodels (page 58-59)

The following part is clear enough.

(Page 59 top)
Replace the entire custom <script> element with the following:

<script type='text/javascript'>
$.getJSON("/get-user-data", function(data) {
var viewModel = ko.mapping.fromJS(data);
ko.applyBindings(viewModel);
});
</script>

But it is not clear how or where the next two methods 
viewModel.loadUserData() and 
viewModel.saveUserData() 
should be placed with respect to the $getJSON method.
What should the complete script file look like?

13 Replies

SK Shanmugaraja K Syncfusion Team April 12, 2017 12:21 PM UTC

Hi Paul, 
 
Thanks for contacting Syncfusion support, 
 
We have checked your query, the loadUserData and saveUserData both are separate methods. loadUserData method is used to map the JSON objects which is loaded from the server to ViewModel observables, which is updating in the existing ViewModel.  
 
loadUserData method: 
  viewModel.loadUserData = function () { 
       $.getJSON("/get-user-data", function (data) { 
           // update the data in existing ViewModel. 
           ko.mapping.fromJS(data, viewModel); 
       }); 
  } 
 
 
saveUserData method is used to convert the ViewModel into JSON and send that to server. You can call both methods separately.  
 
saveUserData method: 
 
  viewModel.saveUserData = function() { 
      // Convert the viewModel into JSON. 
      var data_to_send = {userData: ko.toJSON(viewModel)}; 
      // Send that JSON data to server. 
      $.post("/save-user-data", data_to_send, function(data) { 
           alert("Your data has been posted to the server!"); 
      }); 
   
 
 
Please let us know if you need further assistance. 
 
Regards, 
Shanmugaraja K 



PV Paul van Bavel replied to Shanmugaraja K April 12, 2017 01:00 PM UTC

Hi Paul, 
 
Thanks for contacting Syncfusion support, 
 
We have checked your query, the loadUserData and saveUserData both are separate methods. loadUserData method is used to map the JSON objects which is loaded from the server to ViewModel observables, which is updating in the existing ViewModel.  
 
loadUserData method: 
  viewModel.loadUserData = function () { 
       $.getJSON("/get-user-data", function (data) { 
           // update the data in existing ViewModel. 
           ko.mapping.fromJS(data, viewModel); 
       }); 
  } 
 
 
saveUserData method is used to convert the ViewModel into JSON and send that to server. You can call both methods separately.  
 
saveUserData method: 
 
  viewModel.saveUserData = function() { 
      // Convert the viewModel into JSON. 
      var data_to_send = {userData: ko.toJSON(viewModel)}; 
      // Send that JSON data to server. 
      $.post("/save-user-data", data_to_send, function(data) { 
           alert("Your data has been posted to the server!"); 
      }); 
   
 
 
Please let us know if you need further assistance. 
 
Regards, 
Shanmugaraja K 


Hi,

Thnx for your reply. Alas it's not a reply I needed.

I understand the purpose of the viewModel.loadUserData() and  viewModel.saveUserData() methods..
What I don't understand is how to merge these methods into the script.
I'll attach the script I have created following the text in the booklet .
I receive a reference error on line 45 because viewmodel is undefined.
So what should the script file look like (in order to work)
Thanks,



SK Shanmugaraja K Syncfusion Team April 13, 2017 12:58 PM UTC

Hi Paul, 
 
Thanks for your update, 
 
We have checked your query, and created simple sample with your requirement [“Merge the loadUserData and saveUserData methods into single script”]. Please refer the below code example, 
 
[JS] 
 
 
    <div class='sample'> 
        <p>Load: <input type="button" value="Load User Data" data-bind="click: loadUserData" /></p> 
        <p>Name: <input data-bind='value: firstName' /></p> 
        <p>Save: <input type="button" value="Save User Data" data-bind="click: saveUserData" /></p> 
    </div> 
    <script> 
        $(document).ready(function () { 
            var viewModel = {}; 
            viewModel.firstName = ko.observable('Knockout JS'); 
            viewModel.loadUserData = function () { 
                $.getJSON("/data.json", function (data) { 
                    // update the data in existing ViewModel. 
                    ko.mapping.fromJS(data, viewModel); 
                    viewModel.firstName(data.name); 
                }); 
            }; 
            viewModel.saveUserData = function () { 
                // Convert the viewModel into JSON. 
                var data_to_send = { userData: ko.toJSON(viewModel) }; 
                // Send that JSON data to server. 
                $.post("/save-user-data", data_to_send, function (data) { 
                    alert("Your data has been posted to the server!"); 
                }).fail(function () { 
                    alert("Ensure the Url before save the data"); 
                }); 
            }; 
            ko.applyBindings(viewModel); 
        }); 
    </script> 
 
 
Also, we have attached the sample with these code examples and the same can be downloaded from the below link, 
 
 
Please find the above sample and check whether this fulfilling your requirement, if not please provide more information about this, so that we can work on this and provide you a better solution. 
 
Regards, 
Shanmugaraja K 



PV Paul van Bavel April 17, 2017 01:29 PM UTC

I'm confused by your answer.

Especially this statement:

"viewModel.firstName = ko.observable('Knockout JS');"

I'm confused because of two reasons:

  1. in "Knockout_Succintly.pdf", on the bottom page 58- top of  page 59  it reads:
    "we’ll use jQuery’s $.getJSON() method to load some initial data from the server
    and let the mapping plug-in dynamically generate observables"

  2. Aside of the complexity of your example (number of files in a visual studio setting), I'm also confused by your example itself.
    I've been following the PDF file from beginning to end. In general it's quit clear except for our current conversation topic.

Once again.

Chapter 7 Accessing External Data, starts with an example without the mapping plugin.

Following the text, at page 58, just before "Mapping Data tot ViewModels", the html file (in my filesystem) looks like (zie attachment: "ExternalData.html"

Further there is a file named "get-user-data" containing one JSON format record (refer to top of page 57 )

This example works just fine.

Now my problem starts on top of page 59.

I've to replace the entire custom <script>  (of ExternalData.html) with the new script on top of page 59.

Of course that isn't too difficult

The result is that the JSON data is loaded at loading the page.

Pushing the Load Data or Save Data buttons looks like the fields reload(?)

--------------------------------------------

Trying to incorporate the load and save methods doesn't work.

Even when I used your suggestion to use $( document ).ready() 

and it looks like the bindings couldn't be parsed (dev console)

So what's wrong



SK Shanmugaraja K Syncfusion Team April 18, 2017 10:56 AM UTC

Hi Paul, 
 
Thanks for your update. 
 
We have checked your reported issue [“Unable to parse bindings - script error”] and we are able to reproduce the issue at our end.  We suggest to use $root.loadUserData and $root.saveUserData in data bind property of button to resolve the issue, which is used to access these methods while binding. Please find the below code example. 
 
[JS] 
 
 
    <form action="#" method="post"> 
        <p>First name: <input data-bind='value: firstName' /></p> 
        <p>Last name: <input data-bind='value: lastName' /></p> 
        <div> 
            Your favorite hobby: 
            <select data-bind='options: activities, value: favoriteHobby'></select> 
        </div> 
        <p><button data-bind='click: $root.loadUserData'>Load Data</button></p> 
        <p><button data-bind='click: $root.saveUserData'>Save Data</button></p> 
    </form> 
    <script type='text/javascript'> 
        function PersonViewModel() { 
            var self = this; 
            self.firstName = ""; 
            self.lastName = ""; 
            self.activities = []; 
            self.favoriteHobby = ""; 
            self.loadUserData = function () { 
                $.getJSON("/get-user-data.json", function (data) { 
                    var viewModel = ko.mapping.fromJS(data); 
                    ko.applyBindings(viewModel); 
                }); 
            } 
            self.saveUserData = function () { 
                var data_to_send = { userData: ko.toJSON(self) }; 
                $.post("/save-user-data", data_to_send, function (data) { 
                    alert("Your data has been posted to the server!"); 
                }).fail(function () { 
                    alert("Ensure the Url before save the data"); 
                }); 
            } 
        } 
        ko.applyBindings(new PersonViewModel()); 
    </script> 
 
 
We have created simple sample with these code example and the same can be downloaded from the below link, 
 
 
Please try the above sample check whether this fulfilling your requirement, if not please share more information about this and if possible please share your sample to achieve your exact requirement. 
 
Regards, 
Shanmugaraja K 



PV Paul van Bavel April 18, 2017 02:03 PM UTC

Thanks again for your effort.
The example you sent me, works. 
However, it also works without the $root property.

BUT, you are explicitly defining the observables while
 THAT shouldn't be necessary when using the mapping plugin.
I once again attached my script with lots of comments (and questions).
I hope it is clear enough by now
Regards. 



SK Shanmugaraja K Syncfusion Team April 19, 2017 07:38 AM UTC

Hi Paul, 
 
Thanks for your update, 
 
We would like to let you know that, we can access only the loadUserData and saveUserData methods with $root property when using inside the PersonViewModel function. And you have mentioned that you have attached the scripts, but we can’t find any attachment here. Could you please check and provide your scripts so that we can work on this and provide you a better solution. 
 
Regards, 
Shanmugaraja K 



PV Paul van Bavel May 3, 2017 02:18 PM UTC

Here is the file withe the requested data.
I hope it is clear enough.
Good luck,
regards

Attachment: ExternalData_8429c627.zip


SI Silambarasan I Syncfusion Team May 5, 2017 01:30 PM UTC

Hi Paul, 
 
Thanks for your update. 
 
We have checked the ‘ExternalData.html’ and it works without using $root property since you have directly updated the values for each property by replaced the mapping.fromJS().   
 
 
 
Also we have checked the other two html files, when enabled the buttons ‘Load Data’ & ‘Save Data’ and it doesn’t work due to the binded functions are become unavailable since in that applybindings() by replacing old viewModel with updated data.  
 
We have modified the provided sample to demonstrate the mapping.fromJS() functionality without defining observable property. Please refer the following code examples. 
 
Solution 1 [ExternalDataUsingKO_Mapping_fase-1.html] 
 
var viewModel = {}; 
 
viewModel.loadUserData = function () { 
    $.getJSON("get-user-data.json", function (data) { 
        ko.mapping.fromJS(data, viewModel); 
    }); 
} 
 
viewModel.saveUserData = function () { 
    var data_to_send = { userData: ko.toJSON(viewModel) }; 
    alert(data_to_send.userData); 
    $.post("save-user-data", data_to_send, function (data) { 
        alert("Your data has been posted to the server!"); 
    }); 
} 
 
$.getJSON("get-user-data.json", function (data) { 
    ko.mapping.fromJS(data, {}, viewModel); 
    ko.applyBindings(viewModel); 
}); 
 
 
Solution 2 [ExternalDataUsingKO_Mapping_fase-2.html] 
 
$.getJSON("get-user-data.json", function (data) { 
    var viewModel = ko.mapping.fromJS(data); 
 
    viewModel.loadUserData = function () { 
        $.getJSON("get-user-data.json", function (data) { 
            ko.mapping.fromJS(data, viewModel); 
        }); 
    }; 
 
    viewModel.saveUserData = function () { 
        var data_to_send = { userData: ko.toJSON(viewModel) }; 
        alert(data_to_send.userData); 
        $.post("save-user-data", 
                data_to_send, 
                function (data) { 
                    alert("Your data has been posted to the server!"); 
                } 
                ); 
    } 
 
    ko.applyBindings(viewModel); 
}); 
 
 
 
Could you please check the above sample and let us know whether is this fulfilling your requirement, if not please share us more information regarding this so that we can analyze based on that and provide you a better solution. The information provided would be great help for us to proceed further. 
 
Regards, 
Silambarasan 



PV Paul van Bavel May 9, 2017 10:43 AM UTC

Thnx. It looks as if things are working now.
See my attachment with your suggested changes.

However there still is one thing that bothers me. 
The output file "save-user-data" does have to exist before running the script.
Second, if that file exists, everything works fine, however the output file remains empty.  
WHY?
Following is the dev-console / network output for the POST action from the script .

D:\www\KnockOut.JS. Examples\succinctly-syncfusion\code\ExternalDataUsingKO_Mapping_fase-3.html
  1. General
    1. Request URL:
      http://localhost/KnockOut.JS.%20Examples/succinctly-syncfusion/code/save-user-data
    2. Request Method:
      POST
    3. Status Code:
      200 OK
    4. Remote Address:
      [::1]:80
    5. Referrer Policy:
      no-referrer-when-downgrade
  2. Response Headersview source
    1. Accept-Ranges:
      bytes
    2. Connection:
      Keep-Alive
    3. Content-Length:
      0
    4. Date:
      Tue, 09 May 2017 10:20:57 GMT
    5. ETag:
      "0-54f13ede28cb9"
    6. Keep-Alive:
      timeout=5, max=100
    7. Last-Modified:
      Tue, 09 May 2017 09:24:57 GMT
    8. Server:
      Apache/2.4.25 (Win64) PHP/7.1.4
  3. Request Headersview source
    1. Accept:
      */*
    2. Accept-Encoding:
      gzip, deflate, br
    3. Accept-Language:
      en-US,en;q=0.8,nl;q=0.6,de-DE;q=0.4,de;q=0.2,fr-FR;q=0.2,fr;q=0.2
    4. Connection:
      keep-alive
    5. Content-Length:
      496
    6. Content-Type:
      application/x-www-form-urlencoded; charset=UTF-8
    7. Cookie:
      _gk=%7B%22t%22%3A%7B%7D%2C%22p%22%3A%7B%22uuid%22%3A%220f0b5507-163d-45d8-a9bc-6d866eec24b3%22%7D%7D; __utma=1.951913410.1475421850.1475421850.1475421850.1; pmaCookieVer=5; pma_lang=en; pma_collation_connection=utf8mb4_unicode_ci; pmaUser-1=%7B%22iv%22%3A%22kBWo0Wr8Fj81wwZz%2BV4tBQ%3D%3D%22%2C%22mac%22%3A%226648ea828cbfa3a03205a74e08312bae9d6ee463%22%2C%22payload%22%3A%2261VGBQmJI6PgZu4ZqBpidg%3D%3D%22%7D
    8. DNT:
      1
    9. Host:
      localhost
    10. Origin:
      http://localhost
    11. Referer:
      http://localhost/KnockOut.JS.%20Examples/succinctly-syncfusion/code/ExternalDataUsingKO_Mapping_fase-3.html
    12. Save-Data:
      on
    13. User-Agent:
      Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/57.0.2987.133 Safari/537.36
    14. X-Requested-With:
      XMLHttpRequest
  4. Form Dataview sourceview URL encoded
    1. userData:
      {"firstName":"John","lastName":"Smith","activities":["Golf","Kayaking","Web Development"],"favoriteHobby":"Golf","__ko_mapping__":{"ignore":[],"include":["_destroy"],"copy":[],"observe":[],"mappedProperties":{"firstName":true,"lastName":true,"activities":true,"favoriteHobby":true},"copiedProperties":{}}}



SK Shanmugaraja K Syncfusion Team May 10, 2017 06:47 AM UTC

Hi Paul, 
 
Thanks for your update. 
 
We would like to let you know that the $.post method is used only post the data into the server. If you want to save the data, you need to handle manually in the server side. Please check the below code example, 
 
[ExternalDataUsingKO_Mapping_fase-2.html] 
 
[JS] 
 
            $.getJSON("get-user-data.json", function (data) { 
                //… 
                viewModel.saveUserData = function () { 
                    var data_to_send = { userData: ko.toJSON(viewModel) }; 
                    // SaveData.asmx - Web Service name; Save_User_Data - method name. 
                    // datavalue- The data which send to server 
                    $.post("SaveData.asmx/Save_User_Data", { datavalue: data_to_send.userData }, 
                            function (data) { 
                                if (data == "Success") 
                                    alert("Your data has been posted to the server!"); 
                                else 
                                    alert("Failed to update!"); 
                            } 
                          ); 
                } 
                ko.applyBindings(viewModel); 
            }); 
 
 
 
[CS] 
 
 
    public class SaveData : WebService 
    { 
        [WebMethod] 
        [ScriptMethod( ResponseFormat = ResponseFormat.Json)] 
        public void Save_User_Data() 
        { 
            // datavalue - Received from client side. 
            string data = HttpContext.Current.Request.Params["datavalue"]; 
            string path = Server.MapPath("~/JsonFile/"); 
            try 
            { 
                //write the data into the SavedData.json file. 
                File.WriteAllText(path + "SavedData.json", data); 
                Context.Response.Write("Success"); 
            } 
            catch 
            { 
                Context.Response.Write("Failure"); 
            } 
        } 
    } 
 
 
 
Also, we have attached sample with these code example and the same can be downloaded from the below link, 
 
 
Regards, 
Shanmugaraja K 



PV Paul van Bavel May 10, 2017 12:16 PM UTC

OK. Thanks for your patient answerring my questions.

Clear enough. 
Except what language are you using for the write-to-disk part (C# ??, C-Sharp??)
"[CS] 
 
 
    public class SaveData : WebService 
    { 
        [WebMethod] 
"


SK Shanmugaraja K Syncfusion Team May 11, 2017 10:55 AM UTC

Hi Paul, 
 
Thanks for your update. 
 
We are happy to hear your issue has been resolved. We have used C# code to write the received data into the disk. 
 
Please let know if you need further assistance. 
 
Regards, 
Shanmugaraja K 


Loader.
Live Chat Icon For mobile
Up arrow icon