Search code examples
javascriptc#asp.net-mvcmodel-view-controllerknockout-mvc

ASP.NET MVC Knockout button click call POST API


I have a table (list) on my front end in html, and foreach row, I have a button:

...
<td>
  <button data-bind="click: sendDataToApi">Test button</button>
</td>
...

and in the .js file I have something like this:

define(['viewmodels/shell', 'durandal/services/logger', 'plugins/dialog', 'viewmodels/shell', 'toastr', 'knockout', 'kovalidationconfig', 'plugins/router', 'typeahead.bundle'],
    function (shell, logger, dialog, shell, toastr, ko, kvc, router, typeahead) {
        var vm = {
            activate: activate,
            shell: shell,
            data: ko.observableArray([]),
            close: function () {
                $(window).off('popstate', vm.goBack);
                $(window).off('resize', adjustModalPosition);
                dialog.close(vm, 'cancel');
            },
            goBack: function () {
                $(window).off('popstate', vm.goBack);
                $(window).off('resize', adjustModalPosition);
                dialog.close(vm, 'back');
            },
            editPreregisteredChildren: function () {
                router.navigate("#/function/" + this.id);
            },
           
            currentPage: ko.observable(1),
            itemsPerPage: ko.observable(10),
            hasNextPage: ko.observable(false),
            previousPage: previousPage,
            nextPage: nextPage,
            sendDataToApi: function () {console.log("sdsdsds")},
            searchCriteria: ko.observable(''),
            applySearch: applySearch,
            locations: ko.observableArray([]),
            locationId: ko.observable(),
            LocationName: ko.observable(),
            exportHref: ko.observable("/spa/ExportSchedulings"),
            bindingComplete: function (view) {
                bindFindLocationEvent(view);
            }
        };

        function sendDataToApi() {
            console.log("hello.")
        };

    });

so, firstly, I want to get console.log("something") to work.

for now Im getting error in my console in chrome:

Uncaught ReferenceError: Unable to process binding "click: function(){return sendDataToApi }"
Message: sendDataToApi is not defined

I dont get it why?

after that I need to do an ajax call to my controller, and the end to call some api in that controller, and return the information if the api call was successfull or not.


Solution

  • I am going to assume that you are trying to display information in a table given the

    <td>
      <button data-bind="click: sendDataToApi">Test button</button>
    </td>
    

    I am also going to assume that that there is a ko:foreach at the table or table-body level. if that is the case then sendDataToApi is associated with the parent vm object and not the object that is currently being used to create the table rows.

    If that is the case then you would need to use the $parent.sendDataToApi or $root.sendDataToApi

    <td>
      <button data-bind="click: $parent.sendDataToApi">Test button</button>
    </td>
    

    or

    <td>
      <button data-bind="click: $root.sendDataToApi">Test button</button>
    </td>
    

    EDIT

    you just need to add a parameter to the receiving function because the knockout passes the current object.

    var serverData = [{
        id: 1,
        name: 'Test 1'
      },
      {
        id: 2,
        name: 'Test 2'
      },
      {
        id: 3,
        name: 'Test 3'
      },
    ];
    
    function ViewModel() {
      var self = this;
      self.data = ko.observableArray([]);
    
      self.checkServer = function checkServer(row) {
        console.log(ko.toJS(row));
      }
    
    
      self.fillTable = function fillTable() {
        var mappedData = serverData.map(r => new RowViewModel(r));
        self.data(mappedData);
      }
    
    
      
    }
    
    function RowViewModel(data) {
      var self = this;
      self.id = ko.observable(data.id || 0);
      self.name = ko.observable(data.name || '');
    
    
    }
    ko.applyBindings(new ViewModel());
    <link href="https://cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/4.6.0/css/bootstrap.min.css" rel="stylesheet"/>
    
    <script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
    <button class="button" data-bind="click: fillTable">Fill Table</button>
    <table class="table">
    
      <tbody data-bind="foreach: data">
        <tr>
          <td data-bind="text: id"></td>
          <td data-bind="text: name"></td>
          <td>
            <button data-bind="click: $parent.checkServer">Check Server</button>
          </td>
        </tr>
      </tbody>
    </table>