格式化一个 redux-form 字段(添加一个单元)
Format a redux-form field (add a unit)
我正在尝试向 redux 字段添加一个单元。
该字段包含一个距离。
我想设置一个最大值,并在该值之后添加单位。
如果我在该字段中输入“1000”,该字段应显示“100cm”,并且保存到状态的值应为“100”。
如果输入太高,我会使用标准化器来更改值。那部分有效。
我使用格式化程序在值后添加单位,但我认为这不是一个好方法。
当格式化程序将单位添加到值时,规范化程序接收到的值包含该单位。
该单位仅用于展示目的。我不想在标准化器中看到它,也不想在商店中坚持使用它。
有什么办法吗
这是我的代码:
// Normalizer
const lessThanNormalizer = maxValue =>
newValue =>
return newValue<maxValue ? newValue : maxValue;
// Formatter
const unitFormatter = unit =>
value =>
value+" "+unit;
// Field component
<Field
name= "hardware.distance"
component= {renderMaterialTextField}
type= "text"
label= "Distance"
normalize= {lessThanNormalizer(100)}
format= {unitFormatter("cm")}
/>
提前致谢!!
我设法通过在 parse
属性上添加 parser 来实现它。 (doc)
// Normalizer
const lessThanNormalizer = maxValue => newValue => newValue < maxValue ? newValue : maxValue;
// Formatter
const unitFormatter = unit => value => value !== undefined ? value + " " + unit : '';
// Parser
const cmParser = value => {
return value
.replace(/ /g, "")
.replace(/c/g, "")
.replace(/m/g, "")
}
/* ... */
<Field
name="field"
component="input"
normalize={lessThanNormalizer(100)}
format={unitFormatter('cm')}
parse={cmParser}
/>
/* ... */
虽然这行得通,但更改输入中的内容也有点烦人,因为您需要将光标设置在“cm”之前才能修改数字,但这行得通。
如果你想让它更方便,你可能想通过 ref 以编程方式设置光标位置。
此外,商店中的状态不包含字符串末尾的 cm
。
我找到了解决办法。
现在一切正常。
希望对其他人有所帮助。
import React from 'react'
import renderMaterialTextField from "../../../renderMaterialTextField";
import {Field, getFormMeta} from "redux-form";
import {connect} from "react-redux";
// Get a nested object from a string of type w.x[y].z
let resolve = (s,o) => {
s = s.replace(/\[(\w+)\]/g, '.'); // convert indexes to properties
s = s.replace(/^\./, ''); // strip a leading dot
let a = s.split('.');
for (let i = 0, n = a.length; i < n; ++i) {
let k = a[i];
if (k in o) { o = o[k]; } else { return; }
}
return o;
};
// Normalizer (limit the value)
const minMaxNormalizer = (min,max) => (newValue, previousValue) => {
if(newValue.trim()==="") newValue=0;
newValue = parseFloat(newValue);
if(isNaN(newValue)) {
newValue=previousValue;
}else if(newValue>max) {
return max;
}else if(newValue<min) {
return min;
}
return newValue;
};
// Formatter (add the unit)
const unitFormatter = (unit,formMeta) => (value, name) => {
if(value===0) return "";
let fieldMeta = resolve(name, formMeta); //Get the meta of the field
if(String(value).trim()==="" || (formMeta[name.split('.')[0]]!==undefined && fieldMeta!==undefined && !!fieldMeta.active)) return value;
return value+" "+unit;
};
class MyComponent extends React.Component {
render() {
return (
<>
<Field
name="hardware.device1.distance"
component={renderMaterialTextField}
type="text"
label="Distance"
normalize={minMaxNormalizer(0,100)}
format={unitFormatter("cm", this.props.formMeta)}
/>
<Field
name="hardware.device1.volume"
component={renderMaterialTextField}
type="text"
label="Volume"
normalize={minMaxNormalizer(0,50)}
format={unitFormatter("L", this.props.formMeta)}
/>
</>
)
}
}
MyComponent = connect(
state => ({
formMeta: getFormMeta('myForm')(state)
})
)(MyComponent);
export default MyComponent;
我正在尝试向 redux 字段添加一个单元。 该字段包含一个距离。 我想设置一个最大值,并在该值之后添加单位。
如果我在该字段中输入“1000”,该字段应显示“100cm”,并且保存到状态的值应为“100”。
如果输入太高,我会使用标准化器来更改值。那部分有效。
我使用格式化程序在值后添加单位,但我认为这不是一个好方法。
当格式化程序将单位添加到值时,规范化程序接收到的值包含该单位。 该单位仅用于展示目的。我不想在标准化器中看到它,也不想在商店中坚持使用它。 有什么办法吗
这是我的代码:
// Normalizer
const lessThanNormalizer = maxValue =>
newValue =>
return newValue<maxValue ? newValue : maxValue;
// Formatter
const unitFormatter = unit =>
value =>
value+" "+unit;
// Field component
<Field
name= "hardware.distance"
component= {renderMaterialTextField}
type= "text"
label= "Distance"
normalize= {lessThanNormalizer(100)}
format= {unitFormatter("cm")}
/>
提前致谢!!
我设法通过在 parse
属性上添加 parser 来实现它。 (doc)
// Normalizer
const lessThanNormalizer = maxValue => newValue => newValue < maxValue ? newValue : maxValue;
// Formatter
const unitFormatter = unit => value => value !== undefined ? value + " " + unit : '';
// Parser
const cmParser = value => {
return value
.replace(/ /g, "")
.replace(/c/g, "")
.replace(/m/g, "")
}
/* ... */
<Field
name="field"
component="input"
normalize={lessThanNormalizer(100)}
format={unitFormatter('cm')}
parse={cmParser}
/>
/* ... */
虽然这行得通,但更改输入中的内容也有点烦人,因为您需要将光标设置在“cm”之前才能修改数字,但这行得通。
如果你想让它更方便,你可能想通过 ref 以编程方式设置光标位置。
此外,商店中的状态不包含字符串末尾的 cm
。
我找到了解决办法。 现在一切正常。
希望对其他人有所帮助。
import React from 'react'
import renderMaterialTextField from "../../../renderMaterialTextField";
import {Field, getFormMeta} from "redux-form";
import {connect} from "react-redux";
// Get a nested object from a string of type w.x[y].z
let resolve = (s,o) => {
s = s.replace(/\[(\w+)\]/g, '.'); // convert indexes to properties
s = s.replace(/^\./, ''); // strip a leading dot
let a = s.split('.');
for (let i = 0, n = a.length; i < n; ++i) {
let k = a[i];
if (k in o) { o = o[k]; } else { return; }
}
return o;
};
// Normalizer (limit the value)
const minMaxNormalizer = (min,max) => (newValue, previousValue) => {
if(newValue.trim()==="") newValue=0;
newValue = parseFloat(newValue);
if(isNaN(newValue)) {
newValue=previousValue;
}else if(newValue>max) {
return max;
}else if(newValue<min) {
return min;
}
return newValue;
};
// Formatter (add the unit)
const unitFormatter = (unit,formMeta) => (value, name) => {
if(value===0) return "";
let fieldMeta = resolve(name, formMeta); //Get the meta of the field
if(String(value).trim()==="" || (formMeta[name.split('.')[0]]!==undefined && fieldMeta!==undefined && !!fieldMeta.active)) return value;
return value+" "+unit;
};
class MyComponent extends React.Component {
render() {
return (
<>
<Field
name="hardware.device1.distance"
component={renderMaterialTextField}
type="text"
label="Distance"
normalize={minMaxNormalizer(0,100)}
format={unitFormatter("cm", this.props.formMeta)}
/>
<Field
name="hardware.device1.volume"
component={renderMaterialTextField}
type="text"
label="Volume"
normalize={minMaxNormalizer(0,50)}
format={unitFormatter("L", this.props.formMeta)}
/>
</>
)
}
}
MyComponent = connect(
state => ({
formMeta: getFormMeta('myForm')(state)
})
)(MyComponent);
export default MyComponent;