具有计算 属性 的敲除映射嵌套数组
Knockout mapping nested array with computed property
我需要计算一组日期时间服务器端,允许更改 date/time 客户端。
下面的代码根据加载服务器数据工作,并将我需要的 iso 字段添加回服务器。
当用户更改 date/time 输入字段时,如何使 iso 字段动态计算?
到目前为止击倒 JS:
var ViewModel = function() {
var self = this;
// ...other first-level observables and funct
function scadenzeNuove(payload) {
ko.mapping.fromJS(payload, {}, this);
this.iso = ko.pureComputed( function() {
var data_re = /^(\d{2})\/(\d{2})\/(\d{4})T(\d{2}):(\d{2})/;
if (!payload.data) {
return false;
};
var data_string = payload.data;
if (!payload.ora) {
data_string = data_string + 'T00:00';
} else {
data_string = data_string + 'T' + payload.ora;
};
var data_match = data_re.exec(data_string) ? data_re.exec(data_string) : false;
if (!data_match) { return false; };
var data = new Date(data_match[3], data_match[2]-1, data_match[1], data_match[4], data_match[5])
return data;
}, this);
};
var scadenzeNuoveMapping = {
create: function(options) {
return new scadenzeNuove(options.data);
},
};
self.scadenzeNuove = ko.observableArray();
self.compScadenze = function(form) {
$.getJSON('{{ compute_scadenza }}', $(form).serialize(), function(data){
ko.mapping.fromJS(data, scadenzeNuoveMapping, self.scadenzeNuove);
});
};
};
var vm = new ViewModel()
ko.applyBindings(vm);
Html:
<div data-bind="if: scadenzeNuove">
<ul data-bind="foreach: scadenzeNuove">
<li>
<span data-bind="text: iso().toLocaleFormat()"></span>
<input type="text" name="n_data" data-bind="value: data">
<input type="text" name="n_ora" data-bind="value: ora">
<input type="text" name="n_desc" data-bind="value: desc">
</li>
</ul>
</div>
我会使用默认构造函数从 ISO 字符串转到具有分隔年、月等的视图模型。首先可观察到。
然后,您可以定义一个计算的 isoString
属性,将这些重新组合成一个字符串,您可以将其发送到服务器。
我强烈建议您编写一些可靠的测试或使用 moment.js 如果您正在使用 Date
s...
const DateTimeSelection = function(isoString) {
const date = new Date(isoString);
this.year = ko.observable(
date.getFullYear()
).extend({ num: true });
this.month = ko.observable(
date.getMonth()
).extend({ num: true });
this.date = ko.observable(
date.getDate()
).extend({ num: true });
this.hour = ko.observable(
date.getHours()
).extend({ num: true });
this.isoString = ko.pureComputed(() =>
new Date(
this.year(), this.month(), this.date(), this.hour()
).toISOString()
);
this.hasChanged = ko.pureComputed(() =>
this.isoString() !== isoString
);
};
ko.extenders.numeric = function(target) {
return ko.computed({
read: target,
write: x => target(Number(x))
});
};
const initialServerData = "2017-06-16T14:00:00.000Z";
const vm = new DateTimeSelection(initialServerData);
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<input type="number" data-bind="textInput: year">
<input type="number" data-bind="textInput: month">
<input type="number" data-bind="textInput: date">
<input type="number" data-bind="textInput: hour">
<div data-bind="text: 'output ' + isoString()"></div>
<div data-bind="ifnot: hasChanged" style="color: green">Has not been altered by user</div>
<div data-bind="if: hasChanged" style="color: red">Has been altered by user</div>
我的错:我引用了静态数据 payload
而不是动态可观察数据 parent
:
function ScadenzeNuove(payload) {
var parent = this;
ko.mapping.fromJS(payload, {}, parent);
parent.iso = ko.pureComputed( function() {
var data_re = /^(\d{2})\/(\d{2})\/(\d{4})T(\d{2}):(\d{2})/;
if (!parent.data()) {
console.log("Not entered any date");
return false;
};
var data_string = parent.data();
if (!parent.ora()) {
data_string = data_string + 'T00:00';
} else {
data_string = data_string + 'T' + parent.ora();
};
var data_match = data_re.exec(data_string) ? data_re.exec(data_string) : false;
if (!data_match) {
console.log('Not a valid date format');
return false;
};
console.log(data_match);
// Array [ "08/06/2017T23:50:00", "08", "06", "2017", "23", "50" ]
var data = new Date(data_match[3], data_match[2]-1, data_match[1], data_match[4], data_match[5])
console.log(data.toLocaleFormat());
console.log(data.getTimezoneOffset());
return data;
}, parent);
parent.toCal = ko.observable(false);
};
我需要计算一组日期时间服务器端,允许更改 date/time 客户端。 下面的代码根据加载服务器数据工作,并将我需要的 iso 字段添加回服务器。
当用户更改 date/time 输入字段时,如何使 iso 字段动态计算?
到目前为止击倒 JS:
var ViewModel = function() {
var self = this;
// ...other first-level observables and funct
function scadenzeNuove(payload) {
ko.mapping.fromJS(payload, {}, this);
this.iso = ko.pureComputed( function() {
var data_re = /^(\d{2})\/(\d{2})\/(\d{4})T(\d{2}):(\d{2})/;
if (!payload.data) {
return false;
};
var data_string = payload.data;
if (!payload.ora) {
data_string = data_string + 'T00:00';
} else {
data_string = data_string + 'T' + payload.ora;
};
var data_match = data_re.exec(data_string) ? data_re.exec(data_string) : false;
if (!data_match) { return false; };
var data = new Date(data_match[3], data_match[2]-1, data_match[1], data_match[4], data_match[5])
return data;
}, this);
};
var scadenzeNuoveMapping = {
create: function(options) {
return new scadenzeNuove(options.data);
},
};
self.scadenzeNuove = ko.observableArray();
self.compScadenze = function(form) {
$.getJSON('{{ compute_scadenza }}', $(form).serialize(), function(data){
ko.mapping.fromJS(data, scadenzeNuoveMapping, self.scadenzeNuove);
});
};
};
var vm = new ViewModel()
ko.applyBindings(vm);
Html:
<div data-bind="if: scadenzeNuove">
<ul data-bind="foreach: scadenzeNuove">
<li>
<span data-bind="text: iso().toLocaleFormat()"></span>
<input type="text" name="n_data" data-bind="value: data">
<input type="text" name="n_ora" data-bind="value: ora">
<input type="text" name="n_desc" data-bind="value: desc">
</li>
</ul>
</div>
我会使用默认构造函数从 ISO 字符串转到具有分隔年、月等的视图模型。首先可观察到。
然后,您可以定义一个计算的 isoString
属性,将这些重新组合成一个字符串,您可以将其发送到服务器。
我强烈建议您编写一些可靠的测试或使用 moment.js 如果您正在使用 Date
s...
const DateTimeSelection = function(isoString) {
const date = new Date(isoString);
this.year = ko.observable(
date.getFullYear()
).extend({ num: true });
this.month = ko.observable(
date.getMonth()
).extend({ num: true });
this.date = ko.observable(
date.getDate()
).extend({ num: true });
this.hour = ko.observable(
date.getHours()
).extend({ num: true });
this.isoString = ko.pureComputed(() =>
new Date(
this.year(), this.month(), this.date(), this.hour()
).toISOString()
);
this.hasChanged = ko.pureComputed(() =>
this.isoString() !== isoString
);
};
ko.extenders.numeric = function(target) {
return ko.computed({
read: target,
write: x => target(Number(x))
});
};
const initialServerData = "2017-06-16T14:00:00.000Z";
const vm = new DateTimeSelection(initialServerData);
ko.applyBindings(vm);
<script src="https://cdnjs.cloudflare.com/ajax/libs/knockout/3.4.2/knockout-min.js"></script>
<input type="number" data-bind="textInput: year">
<input type="number" data-bind="textInput: month">
<input type="number" data-bind="textInput: date">
<input type="number" data-bind="textInput: hour">
<div data-bind="text: 'output ' + isoString()"></div>
<div data-bind="ifnot: hasChanged" style="color: green">Has not been altered by user</div>
<div data-bind="if: hasChanged" style="color: red">Has been altered by user</div>
我的错:我引用了静态数据 payload
而不是动态可观察数据 parent
:
function ScadenzeNuove(payload) {
var parent = this;
ko.mapping.fromJS(payload, {}, parent);
parent.iso = ko.pureComputed( function() {
var data_re = /^(\d{2})\/(\d{2})\/(\d{4})T(\d{2}):(\d{2})/;
if (!parent.data()) {
console.log("Not entered any date");
return false;
};
var data_string = parent.data();
if (!parent.ora()) {
data_string = data_string + 'T00:00';
} else {
data_string = data_string + 'T' + parent.ora();
};
var data_match = data_re.exec(data_string) ? data_re.exec(data_string) : false;
if (!data_match) {
console.log('Not a valid date format');
return false;
};
console.log(data_match);
// Array [ "08/06/2017T23:50:00", "08", "06", "2017", "23", "50" ]
var data = new Date(data_match[3], data_match[2]-1, data_match[1], data_match[4], data_match[5])
console.log(data.toLocaleFormat());
console.log(data.getTimezoneOffset());
return data;
}, parent);
parent.toCal = ko.observable(false);
};