自动更正值的组合框

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。希望对大家有所帮助。