EasyUI Forum
May 11, 2024, 01:50:24 AM *
Welcome, Guest. Please login or register.

Login with username, password and session length
News:
 
   Home   Help Search Login Register  
Pages: [1]
  Print  
Author Topic: methods for displaying and converting with Form and FormField  (Read 8366 times)
chrwei
Full Member
***
Posts: 219


View Profile Email
« on: January 28, 2020, 03:33:15 PM »

I would like to use Form and FormField, but I'd like some of my fields to displayed and edited in metric or Si units based on a user preference, while always being stored in Si units in the model. 

I was thinking of making my own function component that wraps the typical form field and hides it while instead displaying a TextBox with the users preferred units, but i can't work out a manageable way to get the changes back into the formfield since none of these components seem to have a method for setting the value.

one thing that comes to mind is passing a function to change the original model in the parent state.  Form and FormField seems to be able to affect the model without these special function, but i can't quite work out how.

the other is to keep a metric and si copy of each value in the model, but that seem messy and error prone.

is there some way to trigger a formfield, or the textbox inside it, to update the model programatically that I've overlooked?
Logged
jarry
Administrator
Hero Member
*****
Posts: 2264


View Profile Email
« Reply #1 on: January 28, 2020, 07:46:38 PM »

Extending a form field from InputBase is a better solution. This is a very simple example shows how to build a new form field.
Code:
class MyInput extends InputBase {
  renderInput() {
    const props = {
      id: this.props.inputId,
      className: this.inputClasses(),
      style: this.props.inputStyle,
      value: this.text(),
      onFocus: this.focus.bind(this),
      onBlur: this.blur.bind(this),
      onChange: this.handleInputChange.bind(this)
    }
    return (
      <input {...props}></input>
    )
  }
}

Use it in the Form.
Code:
<Form
  style={{ width: 400 }}
  model={this.state.user}
  ...
>
  <FormField name="email" label="Email:">
    <MyInput value={user.email}></MyInput>
  </FormField>
  ...

You can also update the model programatically.
Code:
this.setState({
  user: { email:'newe@gg.com' }
})
Logged
chrwei
Full Member
***
Posts: 219


View Profile Email
« Reply #2 on: January 29, 2020, 03:07:25 PM »

this seems to work

Code:
class MeasureBox extends InputBase {
constructor(props) {
super(props);
}

handleInputChange(e) {
if (this.props.units === "met")
this.setState({ valueMet: e.target.value });

if(e.target.value === "" || isNaN(e.target.value)) {
this.setValue(e.target.value);
} else {
this.setValue(parseFloat(util.toStore(e.target.value, this.props.units)));
}
}

text() {
return this.props.textFormatter(this.state.valueMet === undefined 
? isNaN(this.state.text) ? this.state.text : util.toDisp(this.state.text, this.props.units)
: this.state.valueMet);
}

renderInput() {
const props = {
autoComplete: "off",
className: this.inputClasses(),
id: this.props.inputId,
style: this.props.inputStyle,
value: this.text(),
onFocus: this.focus.bind(this),
onBlur: this.blur.bind(this),
onChange: this.handleInputChange.bind(this),
tabIndex: this.props.tabIndex
}

return (
<input {...props}></input>
)
}
}

had to add the extra value to preserve whatever the user types in from being re-converted.  suggestions on improvements?
Logged
chrwei
Full Member
***
Posts: 219


View Profile Email
« Reply #3 on: January 29, 2020, 03:21:41 PM »

one issue:

Code:
index.js:1437 Warning: Each child in a list should have a unique "key" prop. See https://fb.me/react-warning-keys for more information.
    in span
    in MeasureBox
    ...

in the generated html, the TextBox formfields and my new MeasureBox formfields have all the same properties, but TextBox does not give this warning.  do I just need to suppress it somehow, or did I do something incorrectly?
Logged
jarry
Administrator
Hero Member
*****
Posts: 2264


View Profile Email
« Reply #4 on: January 30, 2020, 04:46:51 AM »

It looks like you lost the 'key' property for your components. This is the code used in the InputBase component.
Code:
renderInput(){
    let pp = {
        autoComplete: 'off',
        className: this.inputClasses(),
        style: this.props.inputStyle,
        value: this.text(),
        id: this.props.inputId,
        disabled: this.props.disabled,
        readOnly: this.props.readOnly||!this.props.editable,
        tabIndex: this.props.tabIndex,
        placeholder: this.props.placeholder,
        onFocus: this.focus.bind(this),
        onBlur: this.blur.bind(this),
        onChange: this.handleInputChange.bind(this)
    }
    return (
        this.props.multiline===true
        ? <textarea ref={ref=>this.inputRef=ref} {...pp}></textarea>
        : <input ref={ref=>this.inputRef=ref} {...pp}></input>
    )
}
Logged
chrwei
Full Member
***
Posts: 219


View Profile Email
« Reply #5 on: February 04, 2020, 01:50:43 PM »

without changing anything, I'm only getting this intermittently, and mostly not.  will address later if it comes back reliably.
Logged
chrwei
Full Member
***
Posts: 219


View Profile Email
« Reply #6 on: February 10, 2020, 01:38:44 PM »

it's doing it every time now.  maybe it was before and I scrolled past, I had a lot of console logging at the time.

I tried adding key to the props that get copied, no effect, which isn't surprising since I'm not passing a key.

I'm calling my component like:

Code:
			<FormField name="fieldname" style={{ marginBottom: "5px", marginRight: "10px" }} label="Field Name">
<MeasureBox value=5 units="si" />
</FormField>

the error points to the span that InputBase generates, I'm not sure what clue that holds.
Logged
chrwei
Full Member
***
Posts: 219


View Profile Email
« Reply #7 on: February 27, 2020, 04:02:43 PM »

so adding "key: this.props.key" didn't work, but "key: 1" did.
Logged
Pages: [1]
  Print  
 
Jump to:  

Powered by MySQL Powered by PHP Powered by SMF 1.1.18 | SMF © 2013, Simple Machines Valid XHTML 1.0! Valid CSS!