【问题标题】:How to update property on KO object for when a radio button is checked/clicked?如何在选中/单击单选按钮时更新KO对象的属性?
【发布时间】:2015-02-04 02:31:18
【问题描述】:

我已阅读有关 knockoutjs 的文档,并且我了解单选按钮使用检查绑定。对我来说,这个问题是绑定的工作方式不适合我的场景。 In their examples, a radio button is assigned a value and when the radio button is selected, it validates the value of the radio button versus a value in a ko.computed function to determine which radio button was checked.但是,在下面的示例中,每个表格行都有一个单选按钮。

当他们为一行选择单选按钮时,我需要属性“IsPrimary”更新为 true。单选按钮的名称相同可防止多选。我已经能够为 KO 更新属性,但它不会更新我的 mvc 模型中的属性以进行回发,也不会检查单选按钮以显示它已被选中。

 <table data-bind="foreach: details">
            <tr>
                <td>
                    <div>
                        <input data-bind="value: StandardAccountNo, attr: {name: 'NewAccountGroupDetails[' + $index() + '].StandardAccountNo'}" />
                    </div>
                </td>
                <td>
                    <div class="radiobutton">
                        <input type="radio" data-bind="click: $parent.markPrimary, attr: {value: $index()}" name="primary" />
                    </div>
                </td>
                <td>
                    <a href="#" data-bind="click: $parent.removeDetail">Remove</a>
                </td>
           <tr>
</table>

 <button data-bind="click: addDetail">New</button>

淘汰赛

    var Detail = function () {
    this.StandardAccountNo = ko.observable(new Date());
    this.IsPrimary = ko.observable(false);
    this.EffectiveDate = ko.observable(formattedDate(new Date()));
    this.EndDate = ko.observable(formattedDate(new Date()));
};

function ViewModel() {
    var self = this;
    var rawList = '@Html.Raw(new System.Web.Script.Serialization.JavaScriptSerializer().Serialize(Model.NewAccountGroupDetails))';
    self.details = ko.observableArray(convertJSONToKoObservableObject($.parseJSON(rawList)));
    self.details.push(new Detail());

    self.addDetail = function () {
        self.details.push(new Detail());

        $('.datepicker').each(function (i, obj) {
            $(obj).datepicker({ changeYear: true, changeMonth: true });
        });
    }

    self.markPrimary = function () {
        console.log(this);
        this.IsPrimary(true);
        $('.radiobutton').each(function (i, obj) {
            console.log(obj);
        });
    }

    self.removeDetail = function () {
        self.details.remove(this);
    }
}

ko.applyBindings(new ViewModel());

注意:console.logs 输出代表所选行的 KO 对象,这是有效的。下一个仅输出具有单选按钮的每一行并且它可以工作。我试图用它来弄清楚如何将页面上的单选按钮标记为已选中,然后还确保我的 mvc 模型上的属性得到更新,以便它回发。

【问题讨论】:

  • 你正在努力解决这个问题。当您使用 KO 时,您可以轻松获取 JavaScript 对象,并使用 jquery ajax 将其发布到 MVC 控制器,并使用响应(可以是 JSON 或 HTML)来更新当前页面。但是,如果您想继续努力,请创建一个包含多行的普通 MVC 页面,您会发现 &lt;input&gt; 控件有不同的名称,包括末尾的 [n] 之类的索引。一旦您了解 MVC 如何生成这些名称,您就可以使用敲除 name: 绑定来模仿它们,以便在发布到常规 MVC 操作时理解它们
  • 正确,我已经通过 ko foreach 生成了 mvc 名称。这就是它在 Ko 处理页面客户端的更新时更新 mvc 模型以进行回发的方式。你能提供一个你所说的方法的例子吗?

标签: asp.net-mvc-4 knockout.js


【解决方案1】:

试试这个:

 self.markPrimary = function (currentDetail) {
        ko.utils.arrayForEach(self.details(), function (detail) {
            detail.IsPrimary(false);
        });
        currentDetail.IsPrimary(true);
        return true;
 }

【讨论】:

  • 这将更新视图模型,但不会更新用于回发的 mvc 模型,因为单选按钮的名称相同且不遵循 mvc 名称约定。关于如何扩展它以更新我的 mvc 模型以进行回发的想法?
【解决方案2】:

我认为你从 asp.net mvc 的角度来看这个问题有点过分了。尝试先隔离客户端的问题,然后序列化模型,然后处理服务器。

就淘汰赛而言,这就是您正在尝试的方法:http://jsfiddle.net/z1b3mh89/

// items have names and a computed function that knows whether
// this item is primary among other items
function Item(name, primaryObservable) {
    this.name = name;
    this.isPrimary = ko.computed(function (){
        return this.name === primaryObservable();
    }, this);
}

(function(){
    var i = 0;
    var viewModel = {
        primaryItemName: ko.observable(),
        items: ko.observableArray(),
        add: function (a,b,c) {
            this.items.push(new Item(i++ + ' choice', this.primaryItemName));
        }
    };

    // add a few items
    viewModel.add();
    viewModel.add();
    viewModel.add();

    // add a computed that renders a textual representation of the model
    // just to see the changes live (this is only for DEBUG)
    viewModel.log = ko.computed(function () {
        return this.items().map(function (item) {
            return item.name + (item.isPrimary() ? ' [primary]' : '');
        }).join(', ');
    }, viewModel);

    ko.applyBindings(viewModel);
})();

而且你的 html 很简单:

<!-- ko foreach: items -->
<label>
    <input type="radio" name="group1" data-bind="checked: $parent.primaryItemName, value: name"/>
    <span data-bind="text: name"/>
</label>
<!-- /ko -->

<h3>The Items in the view model:</h3>
<p data-bind="text: log"></p>

<button data-bind="click: add">Add Item</button>

一旦您开始工作,您的视图模型应该始终处于良好状态。然后你可以担心序列化并将其发送到 mvc。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-04-27
    • 1970-01-01
    • 1970-01-01
    • 2021-08-23
    相关资源
    最近更新 更多