![](/img/trans.png)
[英]Knockout computed observable with access to observableArray
[英]Knockout: observableArray of arrays of observable inputs
我在项目Flight Management Computer中遇到了route.html的
foreach
绑定问题。
observableArray
value
绑定全部同时更新 对于javascript中的路由,我设置了一个ko.observableArray
Array
的ko.observable
(听起来很混乱,但是下面附有代码):
/* All bindings applied to viewmodel already */
var route = ko.observableArray();
var DEFAULT_ROUTE = [
ko.observable(), // Waypoint Name
ko.observable(), // Lat.
ko.observable(), // Lon.
ko.observable(), // Altitude Restriction
ko.observable(false), // Waypoint isValid
ko.observable('') // Waypoint information
];
单击特定的按钮可以毫无问题地添加DEFAULT_ROUTE
,因为它调用
route.push(DEFAULT_ROUTE);
HTML代码大致如下所示,并且没有UI问题:
<tbody data-bind="foreach: route">
<tr class="wpt-row">
<td><input data-bind="value: $data[0]"></td> <!--waypoint input-->
<td><input data-bind="value: $data[1]"></td> <!--lat. input-->
<td><input data-bind="value: $data[2]"></td> <!--lon. input-->
<td><input data-bind="value: $data[3]"></td> <!--alt. input-->
</tr>
</tbody>
但是 ,如果外部ko.observableArray
有多个数组,则会出现问题,因为在UI和javascript中更改一个输入值都会更新每个数组中的所有值。 例:
var route = ko.observableArray([DEFAULT_ROUTE, DEFAULT_ROUTE, DEFAULT_ROUTE]);
// Then, outside viewmodel (in javascript console)
route()[0][0]('WPT'); // Sets the waypoint of the first input field to be 'WPT'
// Later
route()[0][0](); // 'WPT', correct
route()[1][0](); // 'WPT', incorrect, should be undefined
route()[2][0](); // 'WPT', incorrect, should be undefined
我在另一个文件中设置了类似的foreach
,但<input>
只是作为<span>
,而data-bind
作为text: $data[x]
而不是value
。 该不同的文件可以正常工作,没有任何问题。 不同的文件是log.html
解决route
问题后,当同一数组中的另一个值发生更改时,我希望更新单个数组(一个航点输入字段)中的某些特定值。 IE浏览器
// Scenario 1, waypoint is a valid waypoint with proper coords
var waypoint = 'WAATR';
var coords = getWaypoint(waypoint); // [42.1234, -70.9876]
route()[0][0](waypoint);
// route()[0][0]() is now 'WAATR'
// route()[0][1] and route()[0][2] should automatically update with value `coords[0]` and `coords[1]`
// route()[0][4] should be set to true (valid waypoint)
// Scenario 2, waypoint is NOT a valid waypoint
var waypoint = 'IDK';
var coords = getWaypoint(waypoint); // []
route()[0][0](waypoint);
// route()[0][0]() is now 'IDK'
// route()[0][1] and route()[0][2] should remain undefined, waiting for users to manually input coordinates
// route()[0][4] should be false (invalid waypoint)
我阅读了文档,并且有一个extend
功能,但是我不太了解。 现在的挑战是如何将那些自动填充功能限制为特定的数组(航路点输入字段),而不是(如问题1)限制为整个输入数据表。
如果有人可以提供帮助,我将不胜感激,因为route
是整个项目的最重要特征。
问题1:这是一个与javascript相关的问题,而不是淘汰赛。 您一次又一次地推送对同一对象的引用,从而使您的observableArray包含对同一对象的多个引用。 您应该更改代码,改为使用工厂函数:
var DEFAULT_ROUTE = function(){
return [
ko.observable(), // Waypoint Name
ko.observable(), // Lat.
ko.observable(), // Lon.
ko.observable(), // Altitude Restriction
ko.observable(false), // Waypoint isValid
ko.observable('') // Waypoint information
];
};
然后推:
route.push(DEFAULT_ROUTE());
这样,您每次都添加一个新对象。
您应该真正使用对象而不是数组。 它使所有内容都更容易阅读和理解,并且将极大地帮助调试。
var Route = function() {
this.waypointName = ko.observable();
this.lat = ko.observable();
this.lon = ko.observable();
this.altitudeRestriction = ko.observable();
this.isValid = ko.observable(false);
this.waypointInfo = ko.observable('');
};
就像您已经知道的那样,现在可以通过调用new Route()
来使用它。 您将解决问题1,并获得易于阅读和维护的代码。 解决问题2的正确基础:
由于您现在有了一个定义明确的模型,因此可以开始使用subscribe
或computed
定义属性之间的关系。 您想要更改waypointName
属性并让其他属性自动更新:
var Route = function() {
this.waypointName = ko.observable();
// Automatically updates when you set a new waypoint name
var coords = ko.pureComputed(function() {
return getWaypoint(this.waypointName());
}, this);
// Check if we got correct coords
this.isValid = ko.pureComputed(function() {
return coords().length === 2;
}, this);
// Auto-extract lat from coords, null if invalid
this.lat = ko.pureComputed(function() {
return this.isValid()
? coords()[0]
: null;
}, this);
// Auto-extract lat from coords, null if invalid
this.lon = ko.pureComputed(function() {
return this.isValid()
? coords()[1]
: null;
}, this);
};
现在,您有了一个具有isValid: false
, lat: null
, lon:null
的默认Route
,并且当将waypointName
设置为字符串值时,例如route.waypointName("WAATR")
,所有属性都会自动更新。
嗨, user3297291 ,谢谢您的帮助! 根据您的建议,我能够完成此功能:
var Route = function () {
var self = this;
// Waypoint name
var _fix = ko.observable();
self.fix = ko.pureComputed({
read: function () {
return _fix();
},
write: function (val) {
_fix(val);
var coords = get.waypoint(val);
var isValid = coords[0] && coords[1];
self.lat(coords[0], isValid);
self.lon(coords[1], isValid);
self.info(coords[2]);
}
});
// Latitude
var _lat = ko.observable();
self.lat = ko.pureComputed({
read: function () {
return _lat();
},
write: function (val, isValid) {
_lat(val);
self.valid(isValid ? true : false);
}
});
// longitude
var _lon = ko.observable();
self.lon = ko.pureComputed({
read: function () {
return _lon();
},
write: function (val, isValid) {
_lon(val);
self.valid(isValid ? true : false);
}
});
// Is waypoint valid
self.valid = ko.observable(false);
// Waypoint info
self.info = ko.observable();
};
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.