Отформатируйте поле в форме редукса (добавьте единицу) - PullRequest
0 голосов
/ 11 декабря 2019

Я пытаюсь добавить юнит в поле избыточности. Поле содержит расстояние. Я хотел бы установить максимальное значение и добавить единицу после этого значения.

Если я введу «1000» в поле, поле должно показать «100см», и значение сохранится в состояниидолжно быть "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")}
/>

Заранее спасибо !!

Ответы [ 2 ]

1 голос
/ 11 декабря 2019

Мне удалось сделать это, добавив парсер на parse проп. ( 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", чтобы изменить числа,но это работает.

Если вы хотите сделать это более удобным, вы можете установить программное положение курсора с помощью ссылки.

Кроме того, состояние в хранилище не содержит cm в конце строки.

Кодовый код здесь

0 голосов
/ 12 декабря 2019

Я нашел решение. Теперь все работает очень хорошо.

Я надеюсь, что это может помочь кому-то еще.

enter image description here

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, '.$1'); // 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;
...