Knockout.js:重新选择对数组元素的更改的问题(Knockout.js: Problems relecting changes to an array element)

编程入门 行业动态 更新时间:2024-10-28 14:31:45
Knockout.js:重新选择对数组元素的更改的问题(Knockout.js: Problems relecting changes to an array element)

我试图制作一个基于淘汰的应用程序,我遇到了一个看似无法解决的问题:我正在制作一个操作事件对象列表的UI。 事件对象列表显示在主视图中,其中包含一个事件对象表,其中包含一些可在主视图中更改的属性。

但由于事件对象将包含复杂数据,如子数组等,我希望能够从事件对象列表中打开模态视图,以便对单个事件对象进行详细编辑。 模态视图从与主视图相同的页面内部运行,因此我可以为两个视图使用相同的数据模型。

我能够在模态视图中编辑单个事件对象中的属性,但由于某种原因,更改不会反映在主视图中。 当我迭代事件数组时,我可以看到有问题的数组元素已被更改。 我尝试在数组上执行valueHasMutated方法(这是一个可观察的数组),但这没有任何效果。 非常感谢这里的一些好建议。 我试图编译一个自包含的HTML页面,它比文字更好地解释了问题。 但我担心代码有点长。 但无论如何它在这里:淘汰赛测试

<form id="photograph-form"> <div class="row-fluid span12"> <h4>Events</h4> <table class="table table-condensed table-hover span11 table-striped"> <thead> <tr> <th class="span1">Delete</th><th class="span1">Edit</th><th class="span1">Type</th><th class="span1">Dating basis</th> </tr> </thead> <!-- Todo: Generate table body --> <tbody data-bind="foreach: events"> <tr> <td><a href="#" data-bind="click: $root.removeEvent"><i class="icon-trash"></i></a></td> <td><a data-bind="click: $root.setCurrentEvent" href="#eventView" role="button" data-toggle="modal"> <i class="icon-edit"></i></a></td> <td><select class="input-medium" data-bind="value: event_type, options: event_types, optionsValue: 'identifier', optionsText: 'name'"></select></td> <td><input class="input-medium" data-bind="value: foundation"/> </td> </tr> </tbody> </table> </div> </form> <p>Current item foundation: <span data-bind="text: currentEvent().foundation"></span></p> <div class="row-fluid"> <!-- Button to trigger modal --> <a role="button" class="btn" data-toggle="modal" href="#eventView" data-bind="click: $root.addEvent">New</a> </div> <!-- Modal window --> <div id="eventView" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="eventLabel" aria-hidden="true"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">× </button> <h3 id="eventLabel">Event</h3> </div> <div class="modal-body"> <label for="eventType">Event type</label> <select id="eventType" class="input-medium" data-bind="value: currentEvent().event_type, options: event_types, optionsValue: 'identifier', optionsText: 'name'"></select> <label for="eventFoundation">Dating basis</label> <input id="eventFoundation" class="input-medium" data-bind="value: currentEvent().foundation"/> </div> <div class="modal-footer"> <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true" data-bind="click: $root.updateEvent">OK </button> </div> </div> <script src="js/jquery.js"></script> <script src="js/bootstrap.min.js"></script> <script src="js/knockout.js"></script> <script> var event_types = [ { identifier: "accession", name: "Accession" }, { identifier: "other", name: "Other" }, { identifier: "ownership", name: "Ownership" } ]; var model = new ArtifactModel("photograph"); model.history_description = ko.observable(); model.events = ko.observableArray([ { event_type: "accession", foundation: "Found"}, { event_type: "ownership", foundation: "Museum"} ]); model.currentEvent = ko.observable({ event_type: "accession", foundation: "Found"}); ko.applyBindings(model); function ArtifactModel(artifact_type) { var self = this; self.artifact_id = ko.observable(); self.events = ko.observableArray(); self.currentEvent = ko.observable(); // Operations self.addEvent = function () { self.events.push({ event_type: "", foundation: "" }); self.currentEvent(self.events()[self.events().length - 1]); }; self.setCurrentEvent = function(event) { self.currentEvent(event); console.log("Before: Event.foundation: " + self.currentEvent().foundation); }; self.updateEvent = function(event) { for (var t = 0 ; t < event.events().length ; t++) { console.log("After: Event.foundation: " + event.events()[t].foundation); } event.events.valueHasMutated(); // No effect! } } </script> </body> </html>

I am trying to make a knockout based application an I've run into a seemingly unsolvable problem: I'm making a UI for manipulating a list of event objects. The list of event objects is displayed in a main view, which contains a table of event objects, with a few properties that can be altered in the main view.

But because the event objects will contain complex data, like sub-arrays etc., I want to be able to open a modal view from the list of event objects, in order to do detailed editing of a single event object. The modal view is run from inside the same page as the main view, so I am able to use the same data model for both views.

I am able to edit properties in a single event object in the modal view, but the changes are not reflected in the main view, for some reason. When I iterate the event array, I can see that the array element in question has been changed. I try to execute the valueHasMutated method on the array (which is an observable array), but this has no effect. Would appreciate some good advice here. I've tried to compile a self contained HTML page which explains the problem better than words. But I'm afraid the code is a bit long. But here it is anyway: Knockout Test

<form id="photograph-form"> <div class="row-fluid span12"> <h4>Events</h4> <table class="table table-condensed table-hover span11 table-striped"> <thead> <tr> <th class="span1">Delete</th><th class="span1">Edit</th><th class="span1">Type</th><th class="span1">Dating basis</th> </tr> </thead> <!-- Todo: Generate table body --> <tbody data-bind="foreach: events"> <tr> <td><a href="#" data-bind="click: $root.removeEvent"><i class="icon-trash"></i></a></td> <td><a data-bind="click: $root.setCurrentEvent" href="#eventView" role="button" data-toggle="modal"> <i class="icon-edit"></i></a></td> <td><select class="input-medium" data-bind="value: event_type, options: event_types, optionsValue: 'identifier', optionsText: 'name'"></select></td> <td><input class="input-medium" data-bind="value: foundation"/> </td> </tr> </tbody> </table> </div> </form> <p>Current item foundation: <span data-bind="text: currentEvent().foundation"></span></p> <div class="row-fluid"> <!-- Button to trigger modal --> <a role="button" class="btn" data-toggle="modal" href="#eventView" data-bind="click: $root.addEvent">New</a> </div> <!-- Modal window --> <div id="eventView" class="modal hide fade" tabindex="-1" role="dialog" aria-labelledby="eventLabel" aria-hidden="true"> <div class="modal-header"> <button type="button" class="close" data-dismiss="modal" aria-hidden="true">× </button> <h3 id="eventLabel">Event</h3> </div> <div class="modal-body"> <label for="eventType">Event type</label> <select id="eventType" class="input-medium" data-bind="value: currentEvent().event_type, options: event_types, optionsValue: 'identifier', optionsText: 'name'"></select> <label for="eventFoundation">Dating basis</label> <input id="eventFoundation" class="input-medium" data-bind="value: currentEvent().foundation"/> </div> <div class="modal-footer"> <button class="btn btn-primary" data-dismiss="modal" aria-hidden="true" data-bind="click: $root.updateEvent">OK </button> </div> </div> <script src="js/jquery.js"></script> <script src="js/bootstrap.min.js"></script> <script src="js/knockout.js"></script> <script> var event_types = [ { identifier: "accession", name: "Accession" }, { identifier: "other", name: "Other" }, { identifier: "ownership", name: "Ownership" } ]; var model = new ArtifactModel("photograph"); model.history_description = ko.observable(); model.events = ko.observableArray([ { event_type: "accession", foundation: "Found"}, { event_type: "ownership", foundation: "Museum"} ]); model.currentEvent = ko.observable({ event_type: "accession", foundation: "Found"}); ko.applyBindings(model); function ArtifactModel(artifact_type) { var self = this; self.artifact_id = ko.observable(); self.events = ko.observableArray(); self.currentEvent = ko.observable(); // Operations self.addEvent = function () { self.events.push({ event_type: "", foundation: "" }); self.currentEvent(self.events()[self.events().length - 1]); }; self.setCurrentEvent = function(event) { self.currentEvent(event); console.log("Before: Event.foundation: " + self.currentEvent().foundation); }; self.updateEvent = function(event) { for (var t = 0 ; t < event.events().length ; t++) { console.log("After: Event.foundation: " + event.events()[t].foundation); } event.events.valueHasMutated(); // No effect! } } </script> </body> </html>

最满意答案

问题可能是因为您的event对象本身没有可观察的属性。 尝试将事件定义更改为以下内容:

{ event_type: ko.observable("accession"), foundation: ko.observable("Found") }

您可能需要进行一些其他更改以解释这些属性现在可以观察到的事实,但这意味着从一个位置对对象所做的更改将反映在其他位置。

The problem is probably because your event objects do not have observable properties themselves. Try changing the event definition to something like this:

{ event_type: ko.observable("accession"), foundation: ko.observable("Found") }

You may need to make some other changes to account for the fact that these properties are now observable, but it will mean that changes made to the object from one location will be reflected in other locations.

更多推荐

本文发布于:2023-07-08 02:40:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1071087.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:数组   元素   js   Knockout   element

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!