Search code examples
jqueryknockout.jsknockout-mapping-plugin

Knockout: edited input fields are not updated


I am holding a list of users, whose detail is shown in a Bootstrap dialog. The list is properly populated and the detail data is correctly shown in modal. But as soon as I update one or several input fields, close the dialog and open the detail of another user, I see the edited value instead of the value of second user. If I open the details without editing anything, I always see the correct values.

Problem: In case of editing an input field, the selected user (shown in detail) is not overwritten.

ViewModel:

function UserViewModel() {
    // init
    var self = this;
    self.userList = ko.observableArray([]);
    self.selectedUser = ko.observable([]);
    self.availableGroups = ko.observableArray([]);
    self.errors = ko.observableArray([]);

    self.loadUserList = function() {
        $.ajax({
            type : "POST",
            url : "/user/loadUserList.htm",
            success : function(response) {
                var parsedJSON = $.parseJSON(response);
                self.userList(ko.mapping.fromJS(parsedJSON));
            },
        });
    }

    self.loadUserDetail = function(user) {
        // Set selected user
        self.selectedUser(ko.mapping.fromJS(user));

        // Load available groups
        $.ajax({
            type : "POST",
            url : "/user/loadAvailableGroups.htm",
            success : function(response) {
                var parsedJSON = $.parseJSON(response);
                self.availableGroups(ko.mapping.fromJS(parsedJSON));

                registerClickListener();
                initOrdinaryTooltips();
                $("#user-dialog").modal('show');
            },
        });
    }

    self.addUser = function() {
        self.loadUserDetail(ko.observable([]));
        $("#user-dialog").modal('show');
    }

    self.saveUser = function() {
        // select all assigned groups
        $('#assigned-select option').prop('selected', true);

        var formJson = $("#user-form").serializeArray();
        $.ajax({
            type : "POST",
            url : "/user/saveUser.htm",
            data: formJson,
            success : function(response) {
                var parsedJSON = $.parseJSON(response);
                if(parsedJSON.errors.length == 0){
                    $("#user-dialog").modal('hide');
                } else {
                    initErrorTooltips();
                }
            },
            error : function(e) {
                showErrorBox('Error: ' + e.status);
            }
        });
    }

    self.cancel = function() {
        $("#user-dialog").modal('hide');
    }
}

HTML:

<div class="form-group has-warning">
    <label class="control-label"><spring:message code="masterdata.user.firstName" /></label>
    <input type="text" class="form-control input-sm" data-bind='attr:{value: selectedUser().firstName}' name="user.firstName" />
    <!-- ko foreach: errors() -->
        <!-- ko if: key === 'user.firstName' -->
            <span data-bind='text: value' class="spring-error  fa fa-lg fa-exclamation-circle"></span> 
        <!-- /ko -->
    <!-- /ko -->
</div>

Solution

  • The HTML snippet you provided does not show how the modal is opened and what happens before and afterwards. However, I recommend you to use the value binding instead of the attr binding with your form elements.