KnockoutJS - Print iteration index as input name

邮差的信 提交于 2019-12-13 14:41:28

问题


I am trying to create my first KnockoutJS form view in combination with Spring MVC's @ModelAttribute binding.

  • Data is loaded over Ajax and populated with KnockoutJS
  • Data is added over KnockoutJS
  • Data is removed over Ajax and KnockoutJS
  • Data will be saved with an normal POST submit to Spring MVC controller.

To bind the form inputs to a Spring MVC controller, I need the iteration index from KnockoutJS. So I tried following:

But the values from my database are never bound like they are when I am bind them with data-bind='value: key'. Can you help me, finding the mistake?

JSP:

<form:form modelAttribute="configurationHelper" action="/saveConfigurationList.htm" method="POST" id="configuration-form" class="form-inline">
    <tbody data-bind="foreach: configurations">
        <tr>
            <td>
                // this is working
                <input data-bind='value: key' class="form-control input-sm" type="text"/>
                // this is not working
                <input data-bind='attr:{value: key, name:configurationHelper.configurations[$index].key' class="form-control input-sm" type="text"/> 
            </td>
            <td>
                <a href='#' data-bind='click: $root.removeConfiguration' class="ordinary-tooltip" title='<spring:message code="general.delete"/>'>
                    <i class="fa fa-lg fa-trash-o "></i>
                </a>
            </td>
         </tr>
    </tbody>
</form:form>

ModelView:

function ConfigurationViewModel() {
    var self = this;
    self.configurations = ko.observableArray([]);

    self.loadConfigurations = function() {
        $.ajax({
            type : "POST",
            url : "/loadConfigurationList.htm",
            success : function(response) {
                var responseArray = JSON.parse(response);
                var mappedConfigurations = $.map(responseArray.configurations, function(configuration) {
                    return new Configuration(configuration);
                });
                self.configurations(mappedConfigurations);
            },
            error : function(e) {
                alert('Error: ' + e.status);
            }
        });
    }

    self.saveConfigurationList = function() {
        $("#configuration-form").submit();
    }

    self.addConfiguration = function() {
            self.configurations.push({
                id: 0,
                key: "",
                value: "",
        });
    };

    self.removeConfiguration = function(configuration) {
        if(confirm(springMessageGeneralDeleteReally)){
            $.ajax({
                type : "POST",
                url : "/deleteConfiguration.htm",
                data: {"configurationId": configuration.id},
                success : function(response) {
                    self.configurations.remove(configuration);
                },
                error : function(e) {
                    alert('Error: ' + e.status);
                }
            });
        }
    };
}


function Configuration(data) {
    this.id = ko.observable(data.id);
    this.key = ko.observable(data.key);
    this.value = ko.observable(data.value);
}

Summary:

  • Knockout should only take care of binding the values (loaded with AJAX) to the inputs and display the correct input-name. (to bind the input-value back to the Spring MVC controller)
  • configurationHelper is a request parameter and should not bother Knockout. It is only available to bind the list of configurationHelper.configurations to Spring MVC.

Following form is properly bound to Spring MVC controller:

<form:form modelAttribute="configurationHelper" action="/leina16/configuration/saveConfigurationList.htm" method="POST" id="configuration-form" class="form-inline">
    <form:input path="configurations[0].key" class="form-control input-sm"/>
</form:form>

Now I want to extend inputs with Knockout JS so I need at least the data-bind attribute as well as the foreach: $index from Knockout:

<tbody data-bind="foreach: configurations">
    <input data-bind='attr:{value: key, name:"configurations[$index].key}' class="form-control input-sm" type="text"/>
</tbody>

But the snipped above is neither bound to Spring MVC controller method nor the values are populated.


回答1:


You have a missing } and are probably getting an error about Knockout being unable to parse bindings.

Change:

'attr:{value: key, name:configurationHelper.configurations[$index].key'

To:

'attr:{value: key, name:configurationHelper.configurations[$index].key}'

As configurationHelper is defined outside of your foreach loop, you'll need to reference this using $parent or $root:

'attr:{value: key, name:$parent.configurationHelper.configurations[$index].key}'



回答2:


Solution:

Add quotes to "non-Knockout" elements and use $index() function.

<tbody data-bind="foreach: configurations">
    <tr>
        <td>
            <input data-bind='attr:{value: key, name:"configurations["+$index()+"].key"}' class="form-control input-sm" type="text"/>
        </td>

     </tr>
 </tbody>


来源:https://stackoverflow.com/questions/25385994/knockoutjs-print-iteration-index-as-input-name

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!