knockout - 在渲染完最后一个项目后执行代码

时间:2013-05-05 14:43:50

标签: knockout.js foreach knockout-2.0

我正在使用jquery quicksearch来搜索由knockout foreach循环填充的表。 在foreach结束后,quicksearch元素需要启动 。 我尝试了几种方法,但到目前为止都没有成功。

我尝试使用'afterRender',但无法确定当前项是否是该集合中的最后一项, 我也试过使用bindingHandlers,但后来我得到了一个长度为0而不是长度为2005的集合。

这样:

  1. 在foreach循环中找到最后一个元素的最佳方法是什么?
  2. 在这种特定情况下实施它的最佳方式是什么?
  3. 这是我的观点:

        <tbody data-bind="foreach: containers">
            <tr>
                <td><span data-bind="text: code"></span></td>
                <td><span data-bind="text: typeName"></span></td>
                <td><span data-bind="text: parentClient"></span></td>
                <td><span data-bind="text: client"></span></td>
                <td>
                    <a data-bind="attr: { onclick: deleteUrl }">
                        <i class="icon-trash"></i>@delete </a>
                    |
                    <a data-bind="attr: { href: editUrl }">
                        <i class="icon-edit"></i>@edit</a>
                    |
                    <a data-bind="attr: { href: qrUrl }" target="blank">
                        <i class="icon-qrcode"></i>
                        @printQr
                    </a>
                </td>
    
            </tr>
        </tbody>
    

    这是我的淘汰代码:

    function Container(data) {
            var self = this;
            self.id = ko.observable(data.Id);
            self.code = ko.observable(data.Code);
            self.typeName = ko.observable(data.TypeName);
            self.parentClient = ko.observable(data.ParentClient);
            self.client = ko.observable(data.Client);
            self.deleteUrl = ko.computed(function () {
                return "GetModal('/Containers/Delete/" + data.Id + "','containerModal');";
            });
            self.editUrl = ko.computed(function () {
                return '/Containers/Edit/' + data.Id;
            });
    
            self.qrUrl = ko.computed(function () {
                return '/Qr/Index/10?entity=' + data.Id;
            });
        }
     function ContainersViewModel() {
            var self = this;
            self.containers = ko.observableArray([]);
            self.counter = ko.computed(function () {
                return self.containers().length;
            });
    
            $.getJSON("/Containers/Json", function (data) {
                var containers = $.map(data, function (item) {
                    return new Container(item);
                });
    
                self.containers(containers);
            });
    
        };
        ko.applyBindings(new ContainersViewModel());
    

    非常感谢!

    尼尔

5 个答案:

答案 0 :(得分:4)

foreach绑定afterRender选项可以做你想要的,技巧部分是能够知道元素是最后一个。这可以使用提供的参数来解决,如http://jsfiddle.net/n54Xd/中所示。

功能:

this.myPostProcessingLogic = function(elements, data) {
    if(this.foreach[this.foreach.length-1] === data)
        console.log("list is rendered");
};

将为每个元素调用,但“if”将确保代码仅针对最后一个元素运行。

答案 1 :(得分:2)

尝试手动订阅阵列更改。使用subscribe,您将收到有关阵列修改的通知。

如果您在applyBindings调用后订阅,则会在视图的刷新过程之后通知您。

<强> See fiddle

var ViewModel = function () {
    var self = this;

    self.list = ko.observableArray();

    self.add = function () {
        self.list.push('Item');
    }
    self.list.subscribe(function () {
        alert('before');
    });
};
var vm = new ViewModel();
ko.applyBindings(vm);

vm.list.subscribe(function () {
    alert('after');
});

我希望它有所帮助。

答案 2 :(得分:2)

我只用了一点点调整就成功地使用了Ricardo Medeiros Penna的答案。

    this.myPostProcessingLogic = function(elements, data) {
      if(this.foreach._latestValue[this.foreach._latestValue.length-1] === data)
        console.log("list is rendered");
    };

我必须添加_latestValue来获取长度值,现在它正在按预期工作。

答案 3 :(得分:1)

使用节流扩展器,这种方式在完成数组填充后将被调用一次:

  self.counter = ko.computed(function () {
        return self.containers().length;
    }).extend({ throttle: 100 });

答案 4 :(得分:1)

后期补遗,但里卡多上面的回答中的if声明应该是:

if (this.foreach()[this.foreach().length - 1] === data) {
    //Your post processing logic
}

因为foreach是一个功能。很可能为什么Nir weiner在评估时存在问题。