自动更正值的组合框
A combobox that auto-corrects the value
我有一个组合框,其中可以 select 特定的时间跨度,例如:
5 minutes
15 minutes
1 hour
2 hours
1 day
2 days
1 week
2 weeks
它总是向服务器传输分钟数,但用户不会理解“10080”是什么意思(在您尝试计算之前:它是一个星期)。
新要求是用户应该能够在该框中键入任意值。例如。 “20 分钟”、“1 小时 5 分钟”、“2 小时 5 米”或“1 天 6 小时 120 米”;并且,如果该字段以编程方式设置为某个值(例如 75),则该字段应显示正确的字符串(1 小时 15 分钟)
所以我已经编写了一个解析器和一个格式化程序函数(见下文),但是我怎样才能让我的组合框使用它们?
我已经尝试覆盖 rawToValue/valueToRaw 函数对,类似于我在 datefield
代码中发现的:
rawToValue:function(rawValue) {
console.log('rawToValue');
console.log(rawValue);
return this.parse(rawValue) || rawValue || null;
},
valueToRaw:function(value) {
console.log('valueToRaw');
console.log(value);
return this.format(value);
},
但它们没有被调用,我没有得到任何控制台日志输出。
这些是 parser/formatter 函数:
Ext.define('AlarmTimeField',{
extend:'Ext.form.field.ComboBox',
format:function(minutes) {
var a = [];
Ext.each(this.units, function(unit) {
if(minutes >= unit.minutes) {
var unitCount = Math.floor(minutes/unit.minutes);
console.log(unitCount);
minutes = minutes-unitCount*unit.minutes;
a.push("" + unitCount + " " + (unitCount==1?unit.singular:unit.plural));
}
});
return a.join(' ');
},
parse:function(input) {
if(!input) return 0;
var me=this,
inputSplit = input.split(' '),
value = 0,
lastNum = 0;
Ext.each(inputSplit,function(input) {
if(!input) return;
else if(Ext.isNumeric(input)) lastNum = input;
else if(Ext.isNumeric(input[0])) {
var inputUnit = input.slice(-1),
inputValue = input.slice(0,-1);
Ext.each(me.units,function(unit) {
if(inputUnit==unit.abbr) {
value+=unit.minutes*inputValue;
}
});
}
else {
Ext.each(me.units,function(unit) {
if(input==unit.singular || input==unit.plural || input==unit.abbr) {
value+=unit.minutes*lastNum;
}
});
}
});
return value;
},
units:[{
minutes:10080,
abbr:'w',
singular:'week',
plural:'weeks'
},{
minutes:1440,
abbr:'d',
singular:'day',
plural:'days'
},{
minutes:60,
abbr:'h',
singular:'hour',
plural:'hours'
},{
minutes:1,
abbr:'m',
singular:'minute',
plural:'minutes'
}]
});
主要思想是 Ext.form.field.ComboBox
值实际上是 Ext.data.Model
的实例,因此您的值和显示值只是模型属性值,每次更改值/显示值时都必须更新绑定模型实例(这是我的想法,如果我错了请纠正我)。
我认为 Ext.form.field.ComboBox.validator 是解析手动输入值的好地方 (如果输入的值不正确,您可以立即显示错误消息),因此您可以覆盖它像这样:
validator: function (value) {
// TODO: Add regexp value format validator
var minutes = me.parse(value);
// Add check for zero / empty values if needed
if (minutes === 0)
// Add meaningful error message
return 'Incorrect input';
else {
me.setValue(Ext.create('Ext.data.Model', {
value: minutes,
text: value
}));
return true;
}
}
这是一个非常原始的例子,但我认为这个想法很清楚。
要通过 setValue()
方法格式化以编程方式设置的值,您可以覆盖此方法,如下所示:
setValue: function (value) {
// TODO: Add array of values support
if (Ext.isNumber(value))
value = Ext.create('Ext.data.Model', {
value: value,
text: this.format(value)
});
this.callParent([value]);
}
检查此 fork of your fiddle。希望对大家有所帮助。
我有一个组合框,其中可以 select 特定的时间跨度,例如:
5 minutes
15 minutes
1 hour
2 hours
1 day
2 days
1 week
2 weeks
它总是向服务器传输分钟数,但用户不会理解“10080”是什么意思(在您尝试计算之前:它是一个星期)。
新要求是用户应该能够在该框中键入任意值。例如。 “20 分钟”、“1 小时 5 分钟”、“2 小时 5 米”或“1 天 6 小时 120 米”;并且,如果该字段以编程方式设置为某个值(例如 75),则该字段应显示正确的字符串(1 小时 15 分钟)
所以我已经编写了一个解析器和一个格式化程序函数(见下文),但是我怎样才能让我的组合框使用它们?
我已经尝试覆盖 rawToValue/valueToRaw 函数对,类似于我在 datefield
代码中发现的:
rawToValue:function(rawValue) {
console.log('rawToValue');
console.log(rawValue);
return this.parse(rawValue) || rawValue || null;
},
valueToRaw:function(value) {
console.log('valueToRaw');
console.log(value);
return this.format(value);
},
但它们没有被调用,我没有得到任何控制台日志输出。
这些是 parser/formatter 函数:
Ext.define('AlarmTimeField',{
extend:'Ext.form.field.ComboBox',
format:function(minutes) {
var a = [];
Ext.each(this.units, function(unit) {
if(minutes >= unit.minutes) {
var unitCount = Math.floor(minutes/unit.minutes);
console.log(unitCount);
minutes = minutes-unitCount*unit.minutes;
a.push("" + unitCount + " " + (unitCount==1?unit.singular:unit.plural));
}
});
return a.join(' ');
},
parse:function(input) {
if(!input) return 0;
var me=this,
inputSplit = input.split(' '),
value = 0,
lastNum = 0;
Ext.each(inputSplit,function(input) {
if(!input) return;
else if(Ext.isNumeric(input)) lastNum = input;
else if(Ext.isNumeric(input[0])) {
var inputUnit = input.slice(-1),
inputValue = input.slice(0,-1);
Ext.each(me.units,function(unit) {
if(inputUnit==unit.abbr) {
value+=unit.minutes*inputValue;
}
});
}
else {
Ext.each(me.units,function(unit) {
if(input==unit.singular || input==unit.plural || input==unit.abbr) {
value+=unit.minutes*lastNum;
}
});
}
});
return value;
},
units:[{
minutes:10080,
abbr:'w',
singular:'week',
plural:'weeks'
},{
minutes:1440,
abbr:'d',
singular:'day',
plural:'days'
},{
minutes:60,
abbr:'h',
singular:'hour',
plural:'hours'
},{
minutes:1,
abbr:'m',
singular:'minute',
plural:'minutes'
}]
});
主要思想是 Ext.form.field.ComboBox
值实际上是 Ext.data.Model
的实例,因此您的值和显示值只是模型属性值,每次更改值/显示值时都必须更新绑定模型实例(这是我的想法,如果我错了请纠正我)。
我认为 Ext.form.field.ComboBox.validator 是解析手动输入值的好地方 (如果输入的值不正确,您可以立即显示错误消息),因此您可以覆盖它像这样:
validator: function (value) {
// TODO: Add regexp value format validator
var minutes = me.parse(value);
// Add check for zero / empty values if needed
if (minutes === 0)
// Add meaningful error message
return 'Incorrect input';
else {
me.setValue(Ext.create('Ext.data.Model', {
value: minutes,
text: value
}));
return true;
}
}
这是一个非常原始的例子,但我认为这个想法很清楚。
要通过 setValue()
方法格式化以编程方式设置的值,您可以覆盖此方法,如下所示:
setValue: function (value) {
// TODO: Add array of values support
if (Ext.isNumber(value))
value = Ext.create('Ext.data.Model', {
value: value,
text: this.format(value)
});
this.callParent([value]);
}
检查此 fork of your fiddle。希望对大家有所帮助。