Saurabh
Saurabh

Reputation: 674

object HTMLInputElement instead of value in knockout js textInput binding

I want to pre fill fields of the form on load with existing data from database. On page load i am making an ajax call which queries the data and assign the returned data to a knockout observable array.

client.js:

function clientModel()
    {
        var self = this;
        this.lastTenClients = ko.observableArray();
        this.pendingClients = ko.observableArray();
        this.foundCustomerResult = ko.observable();
        this.shouldShowCustomerMessage = ko.observable(false);
        this.foundCustomers = ko.observableArray();

        var base_url = window.location.origin;
        var pathArray = window.location.pathname.split( '/' );
        if(base_url === "http://localhost"){
            var url = base_url+"/"+pathArray[1]+"/client/";
        } else {
            var url = base_url+"/client/";
        }

        $.ajax({
            url: url+"get_last_ten_clients",
            type: "get",
            cache: false,
            success: function(client_list) {
                var data = $.parseJSON(client_list);
                self.lastTenClients(data);
            }
        });

        $.ajax({
            url: url+"get_pending_data_clients",
            type: "get",
            cache: false,
            success: function(client_list) {
                var data = $.parseJSON(client_list);
                self.pendingClients(data);
            }
        });

        this.search_client = function()
        {           
            self.shouldShowCustomerMessage(false);
            self.foundCustomers.removeAll();
            crsf = $("input[name=csrf_test_name]").val();
            dataString = $("#search_client_input").val();
            $.ajax({
                url: url+"search_client_database",
                type: "post",
                cache: false,
                data: {csrf_test_name: crsf, search_client_input: dataString},
                success: function(customer_details) {
                        var data = (customer_details);
                        self.foundCustomers(data);
                },
                error: function(xhr, ajaxOptions, thrownError)
                {
                    alert(xhr.status);
                    alert(thrownError);
                }
            });
        }
    }

    ko.applyBindings(new clientModel());

Sample data in observable after ajax call:

foundCustomers {"id":"1","nameMusicCompany":"Company","natureMusicCompany":"Music"}

In the view i am trying to assign the value using textInput binding like following:

<input type="text" class="form-control input-sm" name="nameMusicCompany" id="nameMusicCompany" placeholder="Name of the Music Company" 
                        data-bind="textInput: nameMusicCompany">

But instead of showing the value "company" it displays [object HTMLInputElement] inside the input box.

Controller:

public function search_client_database()
{
    if(!empty($this->input->post('search_client_input')))
                {
                    $result = $this->client_model->get_client_data($this->input->post('search_client_input'));
                        echo json_encode($result);
                }

}

Model:

public function get_client_data($client_name)
        {
                $client_name = strtoupper($client_name);
                $sql = "SELECT * FROM client_data where UPPER(nameMusicCompany) = ?";
                $query = $this->db->query($sql, array($client_name));

                if($query->num_rows() > 0)
                {
                        return $query->row();
                }

                return false;
        }

Upvotes: 4

Views: 1961

Answers (2)

user3297291
user3297291

Reputation: 23372

In your ajax success callbacks you're setting lastTenClients and pendingClients, which are both observable arrays.

If you mean to render several inputs:

If you want to render all items inside an observable array you'll have to use a foreach data-bind. The HTML markup inside a foreach cannot have a static id property; it is used as a template and could be included many times. Reusing the same id on several HTML elements will get you in to trouble.

As an example, try:

If you mean to render an input for only one of the items that are returned

If the <input> element you've specified only appears once in your page, you'll have to tell it which customer's nameMusicCompany property it has to render. If the property does not exist in the current binding context, it will look for it someplace else and eventually end up in window. (If I'm not mistaken, this is because knockout uses with: $data internally). Because you've named your <input>'s id the same as the property's name, window will contain an HTMLInputElement.

As an example, try:

<!-- ko with: foundCustomers()[0] -->
<input 
  type="text" name="nameMusicCompany" id="nameMusicCompany" 
  data-bind="textInput: nameMusicCompany">
<!-- /ko -->

Upvotes: 0

T.J. Crowder
T.J. Crowder

Reputation: 1074295

What's happening is that Knockout is picking up the predefined nameMusicCompany global created by the browser because you gave your input element an id instead of the nameMusicCompany property of your viewmodel.

You haven't shown us enough of your code for us to tell you how to fix it, but that's what's going on. It could be as simple as that your attribute should be data-bind="foundCustomers.nameMusicCompany", but that's a guess without seeing more of your code.

Upvotes: 5

Related Questions