简体   繁体   中英

Simple KnockoutJS binding doesn't seem to work

There seems to be some error with my KnockoutJS script but I can't figure it out where it's coming from. Here is the HTML code:

    <h2>SendMessage</h2>

<div class="form-group" id="messageSender">
    <label>Select User Type</label>
    <select id="userType" data-bind="options: $parent.userTypes, optionsText: 'type', optionsValue: 'role'
            optionsCaption: 'Select a user type:', value: selectedUserType"></select><br/>
    <label>Select Reciepient</label>
    <select id="reciepient" data-bind="options: $parent.users, optionsText: 'fname', optionsValue: 'id', value: selectedUser, visible: userTypeSelected"></select>
    <br />
    <label>Message Text</label>
    <textarea data-bind="value:messageText, visible: userTypeSelected"></textarea><br/>
    <button data-bind="click:sendMessage">Send</button>
</div>

Here is my JavaScript code:

$(document).ready(function () {


  var messageModel =   function Message(sender_id, reciever_id, messageText) {

        var self = this;

        self.sender_id = ko.observable(sender_id);
        self.reciever_id = ko.observable(reciever_id);
        self.messageText = ko.observable(messageText);
        self.mdate = Date.now();

        //send ajax request to the api  to add a send
        self.addMessage = function () {

            var dataObject = ko.toJSON(this);

            $.ajax({
                url: "/api/messageapi",
                type: 'add',
                data: dataObject,
                contentType: 'application/json',
                success: function (data) {
                    self.sender_id(null);
                    self.reciever_id(null);
                    self.messageText('');

                    alert("Message send successfully!");
                }
            });

        }


    }

var messageViewModel = function () {

        var self = this;

        self.userTypeSelected = ko.observable();
        //List of roles
        self.userTypes = [
           { role: 2, type: "Teacher" },
           { role: 3, type: "Parent" }
        ];

        self.messageText = ko.observable();
        self.users = function () {

            var role = this.userTypeSelected;
            if (role === 2) {
                $.ajax(
              {
                  url: "/api/MessageApi/GetTeachers/" + role,
                  type: 'get',
                  contentType: 'application/json',
                  success: function (data) {
                      return data;
                  },
                  fail: function () {
                      alert("Error occurred while sending data");
                  }
              });
            }


        };

        self.sendMessage = function () {
            alert("You clicked me!");//added this for testing whether the code works or not
        }

    }


    ko.applyBindings(new messageViewModel());
});

What I'm trying to achieve here is the user selects the type of user s/he wants to send a message to. After selecting the user type, the users are fetched from the database through a Web Api(I'm using asp.net mvc5) by making an ajax call and are displayed in a drop-down list . However, when I run the code following things doesn't seem to work:

  • The first drop-down doesn't display anything. However, I have bound it to the userTypes array
  • The send button doesn't respond to click events even though I have bound it to the sendMessage function.
  • The second drop-down list's visibilty is controlled by the userTypeSelected value but it always shows.

There might also be problem's in my ajax calls but the above ones are the obvious problems

What am I doing wrong here? Thanks in advance.

There are a lot of mistakes in your code

  1. You are missing a comma in your select after

    optionsValue: 'role'

  2. You shouldn't use $parent in your bindings just use the name of the property in options: userTypes and options: users

    <select id="userType" data-bind="options: userTypes, optionsText: 'type', optionsValue: 'role', optionsCaption: 'Select a user type:', value: selectedUserType"></select><br /> <label>Select Reciepient</label> <select id="reciepient" data-bind="options: users, optionsText: 'fname', optionsValue: 'id', value: selectedUser, visible: userTypeSelected"></select>
  3. In you first select in this part: value: selectedUserType , selectedUserType property doesn't exist. Did you mean value: userTypeSelected ?

     <select id="userType" data-bind="options: userTypes, optionsText: 'type', optionsValue: 'role', optionsCaption: 'Select a user type:', value: userTypeSelected">
  4. You are missing self.selectedUser = ko.observable(); in your viewModel

  5. Your var messageModel = function Message(...) seems completly pointless as is not referenced anywhere.

  6. self.users = function()... will not work this way. What you need is to setup a function in the change event in the first select to call the $.ajax to load self.users = ko.observableArray()

    • Replace self.users = function()... with self.users = ko.observableArray()

    • Add a self.userTypeChanged function to your viewModel that will call $.ajax and fill the results to the users observableArray.

      • You are missing a pair of () after var role = self.userTypeSelected();
      • In the success callback you need to fill the users observableArray: self.users(data);

This should be the self.userTypeChanged function

    self.userTypeChanged = function () {
        var role = self.userTypeSelected();
        if (role === 2) {
            $.ajax({
                url: "/api/MessageApi/GetTeachers/" + role,
                type: 'get',
                contentType: 'application/json',
                success: function (data) {
                    self.users(data);
                },
                fail: function () {
                    alert("Error occurred while sending data");
                }
            });
        }
    };
  1. Add the change event to the first select to call userTypeChanged :

     <select id="userType" data-bind="options: userTypes, optionsText: 'type', optionsValue: 'role', optionsCaption: 'Select a user type:', value: userTypeSelected, event: { change : userTypeChanged }"></select>

This is the complete code. I hope this helps

HTML

<h2>SendMessage</h2>

<div class="form-group" id="messageSender">
    <label>Select User Type</label>
    <select id="userType" data-bind="options: userTypes, optionsText: 'type', optionsValue: 'role',
        optionsCaption: 'Select a user type:', value: userTypeSelected, event: { change : userTypeChanged }"></select><br />
    <label>Select Reciepient</label>
    <select id="reciepient" data-bind="options: users, optionsText: 'fname', optionsValue: 'id', value: selectedUser, visible: userTypeSelected"></select>
    <br />
    <label>Message Text</label>
    <textarea data-bind="value:messageText, visible: userTypeSelected"></textarea><br />
    <button data-bind="click:sendMessage">Send</button>
</div>

JS

    $(document).ready(function () {
        var messageViewModel = function () {

            var self = this;
            self.selectedUser = ko.observable();
            self.userTypeSelected = ko.observable();
            //List of roles
            self.userTypes = [
                { role: 2, type: "Teacher" },
                { role: 3, type: "Parent" }
            ];

            self.messageText = ko.observable();

            self.users = ko.observableArray();

            self.userTypeChanged = function () {
                var role = self.userTypeSelected();
                if (role === 2) {
                    $.ajax(
                    {
                        url: "/api/MessageApi/GetTeachers/" + role,
                        type: 'get',
                        contentType: 'application/json',
                        success: function (data) {
                            self.users(data);
                        },
                        fail: function () {
                            alert("Error occurred while sending data");
                        }
                    });
                }
            };

            self.sendMessage = function () {
                alert("You clicked me!");//added this for testing whether the code works or not
            }
        }

        ko.applyBindings(new messageViewModel());
    });

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM