KnockoutJS:向映射生成的 ObservableArray 中的对象添加 Observable 属性和函数

发布于 2024-12-19 22:48:43 字数 1117 浏览 0 评论 0原文

我是 KnockoutJS 的新手,我一直在尝试向 < 中生成的对象添加其他属性和方法。 code>ko.observableArray() 由 mapping 插件创建。

这是我要做的:

  • 我有一个 Users 的 JSON 数组,
  • 我使用映射插件创建了 ko.observableArray()
  • 我有一个为每个用户创建表格行的模板,到目前为止一切顺利:o)

这是我想要做的:

每个用户< /code> 有一个名为'IsActive' - 我想将点击事件数据绑定到每个User对象上切换此'的方法IsActive' 属性。

这个问题看起来很有希望,但对我来说似乎是不必要的重复在 JS 中声明整个视图模型(除非我必须这样做!) - 是否可以只扩展生成的对象?

我沿着这些思路思考更多,有一种方法可以声明其他属性或方法,并让它们扩展映射生成的对象,但本文关注的是单个对象,而不是扩展生成的数组中的对象。

代码如下: http://jsfiddle.net/yZkSf/2/ (尚未在 JS fiddle 中工作 - 但我会继续使用它,并在它工作时更新此链接)。

I'm new to KnockoutJS, and I'm stuck trying to add additional properties and methods to the generated objects in the ko.observableArray() as created by the mapping plugin.

Here's where I'm up to:

  • I have a JSON array of Users
  • I've created the ko.observableArray() with the mapping plugin
  • I've got a template that creates table row for each User, so far so good :o)

Here's what I'm trying to do:

Each User has a property called 'IsActive' - I'd like to data-bind a click event to a method on each User object that toggles this 'IsActive' property.

This question looked promising, but it seems like unnecessary duplication to me to have to declare the entire View Model in JS (unless that's the way I have to do it!) - is it possible to just extend the generated object?

I was thinking more along these lines, where there's a way to declare additional properties or methods, and have them extend the mapping generated objects, but this article is concerned with single objects rather than extending objects in a generated array.

Here's the code: http://jsfiddle.net/yZkSf/2/ (not yet working in JS fiddle - but I'll keep playing with it and update this link when I get it working).

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

神也荒唐 2024-12-26 22:48:43

您可以考虑多种选择。

-一种是使用create回调来控制如何创建“用户”对象。您可以自己定义可观察量并添加额外的功能,也可以在单个用户对象上调用映射插件,然后添加额外的功能。

类似于: http://jsfiddle.net/rniemeyer/fkVaK/

-否则,您可以将“toggle”函数放在 viewModel 上,然后将“user”对象传递给它。

1.3 的一个好方法是使用 ko.dataFor 以及 jQuery 的 live/delegate/on 事件委托功能之类的功能。就像: http://jsfiddle.net/rniemeyer/FkjNr/

//unobtrusive event handler
$(".toggle").live("click", function() {
    var user = ko.dataFor(this);
    if (user) {
       viewModel.toggleIsActive(user);
    }
});

如果你不想要使用事件委托,那么您可以使用匿名函数直接传递项目,例如: http://jsfiddle.net/rniemeyer/GpQtN/

编辑:从 2.0 开始,使用 click/event 绑定时当前数据会自动传递到处理程序,因此您可以执行以下操作:

<a href="#" data-bind="click: $root.toggleIsActive"><span data-bind="text: IsActive"></span></a>

There are several options that you could consider.

-One is to use the create callback to control how your "user" objects get created. You can either define the observables yourself and add extra functionality or call the mapping plugin on the individual user object and then add extra functionality.

Would be something like: http://jsfiddle.net/rniemeyer/fkVaK/

-Otherwise, you can place the "toggle" function on your viewModel and then pass the "user" object to it.

A nice way with 1.3, is to use ko.dataFor along with something like jQuery's live/delegate/on event delegation functionality. Would be like: http://jsfiddle.net/rniemeyer/FkjNr/

//unobtrusive event handler
$(".toggle").live("click", function() {
    var user = ko.dataFor(this);
    if (user) {
       viewModel.toggleIsActive(user);
    }
});

If you don't want to use event delegation, then you can pass the item directly using an anonymous function like: http://jsfiddle.net/rniemeyer/GpQtN/

EDIT: as of 2.0, the current data automatically gets passed to the handler when using click/event bindings, so you can just do:

<a href="#" data-bind="click: $root.toggleIsActive"><span data-bind="text: IsActive"></span></a>
最美不过初阳 2024-12-26 22:48:43

这是我使用你和瑞安的答案得出的结果......似乎有效。请留下反馈,因为我是淘汰赛的新手,我自己也很好奇,这是否是一个好方法。

JS:

$(function() {
    $.get("users/getUsers", function(r){
        var vm = ko.mapping.fromJS(r, {
            users: {
                create: function(user){
                    var methods = {
                        toggleIsActive: function(u){u.IsActive(!u.IsActive());},
                        foo: function(u){console.log(u);},
                        bar: function(u){/*whatever*/},   
                    }
                    return $.extend(ko.mapping.fromJS(user.data), methods);
                }
            }
        });
        ko.applyBindings(vm);
    }, 'json');
});

DOM:

<!-- ko foreach: users -->
   <a href="#" data-bind="click: toggleIsActive"><span data-bind="text: IsActive"></span></a>
<!-- /ko -->

This is what I came up with using both your and Ryan's answers... seems to work. Please leave feedback, as I am new to Knockout and curious myself, if this is a good approach.

JS:

$(function() {
    $.get("users/getUsers", function(r){
        var vm = ko.mapping.fromJS(r, {
            users: {
                create: function(user){
                    var methods = {
                        toggleIsActive: function(u){u.IsActive(!u.IsActive());},
                        foo: function(u){console.log(u);},
                        bar: function(u){/*whatever*/},   
                    }
                    return $.extend(ko.mapping.fromJS(user.data), methods);
                }
            }
        });
        ko.applyBindings(vm);
    }, 'json');
});

DOM:

<!-- ko foreach: users -->
   <a href="#" data-bind="click: toggleIsActive"><span data-bind="text: IsActive"></span></a>
<!-- /ko -->
街角迷惘 2024-12-26 22:48:43

我找到了一种方法来做到这一点,但这意味着一旦创建了数组中生成的对象,就对其进行循环。我更喜欢一种无需额外循环即可实现相同结果的方法。

编辑: 就像 RP Niemeyer 在他的回答中建议的那样! ;o)

无论如何,向现有对象添加属性的一种方法是使用jQuery extends() 组合对象。

首先,在新对象中声明额外的属性和函数:

var userModel = {
    toggleIsActive: function() {
        console.log('toggleIsActive called: before: ' + this.IsActive());
        this.IsActive(!this.IsActive());
        // todo: save!
        console.log('toggleIsActive called: after: ' + this.IsActive());
    }
}

然后,在 ko.mapping.fromJS() 调用之后,但在 ko.applyBindings() 之前> 调用,循环遍历生成数组中的对象并扩展它们:

viewModel.users = ko.mapping.fromJSON(/* get JSON */);

for (var i = 0; i < viewModel.users().length; i++) {
    $.extend(viewModel.users()[i], userModel);
}

ko.applyBindings(viewModel);

I've found a way to do it, but it means looping through the generated objects in the array once they've been created.. I'd prefer a way achieve the same result without the additional loop..

EDIT: Like RP Niemeyer suggests in his answer! ;o)

Anyway, one way to add properties to an existing object is to use jQuery extend() to combine the objects.

First, declare the extra properties and functions in a new object:

var userModel = {
    toggleIsActive: function() {
        console.log('toggleIsActive called: before: ' + this.IsActive());
        this.IsActive(!this.IsActive());
        // todo: save!
        console.log('toggleIsActive called: after: ' + this.IsActive());
    }
}

Then, after the ko.mapping.fromJS() call, but before the ko.applyBindings() call, loop through the objects in the generated array and extend them:

viewModel.users = ko.mapping.fromJSON(/* get JSON */);

for (var i = 0; i < viewModel.users().length; i++) {
    $.extend(viewModel.users()[i], userModel);
}

ko.applyBindings(viewModel);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文