Uniforms: Vazco Uniforms in React-Meteor, unable to get value of SelectField onChange

Created on 18 Jun 2019  路  9Comments  路  Source: vazco/uniforms

Refactoring ReactJS form to work with Vazco-Uniforms. Receiving error when executing SelectField onChange method at name: 'condition'

_Uncaught TypeError: Cannot read property 'value' of undefined @ onConditionChange(event) {
    this.setState({condition: event.target.value});_
import React from 'react';
import { Stuffs, StuffSchema } from '/imports/api/stuff/stuff';
import { Grid, Segment, Header } from 'semantic-ui-react';
import AutoForm from 'uniforms-semantic/AutoForm';
import TextField from 'uniforms-semantic/TextField';
import NumField from 'uniforms-semantic/NumField';
import SelectField from 'uniforms-semantic/SelectField';
import SubmitField from 'uniforms-semantic/SubmitField';
import HiddenField from 'uniforms-semantic/HiddenField';
import ErrorsField from 'uniforms-semantic/ErrorsField';
import { Bert } from 'meteor/themeteorchef:bert';
import { Meteor } from 'meteor/meteor';

class AddStuff extends React.Component {

  constructor(props) {
    super(props);
    this.state = {
      condition: ''
    };

    this.condition = React.createRef();

    this.submit = this.submit.bind(this);
    this.insertCallback = this.insertCallback.bind(this);
    this.formRef = null;

  }

  insertCallback(error) {
    if (error) {
      Bert.alert({ type: 'danger', message: `Add failed: ${error.message}` });
    } else {
      Bert.alert({ type: 'success', message: 'Add succeeded' });
      this.formRef.reset();
    }
  }

  submit(data) {
    const { name, quantity, condition } = data;
    const owner = Meteor.user().username;
    Stuffs.insert({ name, quantity, condition, owner }, this.insertCallback);
  }

    onConditionChange(event) {
    this.setState({condition: event.target.value});
    const condition = this.condition.current.value;
    console.log("Condition changed to: " + condition)

    }

  render() {
    return (


      <Grid container centered>
          <Grid.Column>
            <Header as="h2" textAlign="center">Add Stuff</Header>
            <AutoForm ref={(ref) => { this.formRef = ref; }} schema={StuffSchema} onSubmit={this.submit}>
              <Segment>
                <TextField name='name'/>
                <NumField name='quantity' decimal={false}/>
                  <SelectField name='condition' ref={this.condition} value={this.condition.value} onChange={this.onConditionChange}/>
                <SubmitField value='Submit'/>
                <ErrorsField/>
                <HiddenField name='owner' value='[email protected]'/>
              </Segment>
            </AutoForm>
          </Grid.Column>
        </Grid>

    );
  }
}

export default AddStuff;
import { Mongo } from 'meteor/mongo';
import SimpleSchema from 'simpl-schema';
import { Tracker } from 'meteor/tracker';

const Stuffs = new Mongo.Collection('stuff');

const StuffSchema = new SimpleSchema({
  name: String,
  quantity: Number,
  owner: String,
  condition: {
    type: String,
    allowedValues: ['excellent', 'good', 'fair', 'poor', 'sucks'],
    defaultValue: 'good',
  },
}, { tracker: Tracker });

Stuffs.attachSchema(StuffSchema);

export { Stuffs, StuffSchema };

StackOverflow question.

question

Most helpful comment

The other fields are on the same form. I will give this a try and update the outcome, thank you!

All 9 comments

Hi @rtping. At first, please paste the question here instead of a link (or leave the link as an addition) to make sure that if someone else will search for it here will be able to find it easily. Now, let's get to the question.

The error is expected, as the onChange there will receive only value and no the whole event object. Using onChange on a field component is no the right way to work with it almost every time (although it is possible). Use onChange on the form instead. There you'll get (name, value) arguments to do everything you need (it's not stated in the question).

@radekmie Thank you for the quick response! I am performing conditionals on the returned value i.e. if (condition === 'good') { ...}. When you say use onChange on the form instead, you mean within the <AutoForm /> wrapper? I apologize, new to React.

I will update with the original question and markup.

Yes, on AutoForm. It'll be triggered on any field change but you can check the name and react accordingly.

Is it possible to add the condition within SimpleSchema as:

grade: {
        type: String,
        label: "Grade",
        optional: false,
        allowedValues: [
            "Pre-Kindergarten",
            "Kindergarten",
            "1st",
            "2nd",
            "3rd"
        ],
        custom() {
            const grade = this.field('grade');
            if (grade.value === '1st') {
                alert("1st")
                console.log("You have selected 1st")
            } else {
                console.log("You have not selected 1st")
            }
        }
    },

No, it's not possible out-of-the-box. You can do it in the form onChange by extracting the field definition, but it's rather an advanced way to do it in general. What exactly you want to achieve? Doing it on a form level should be enough.

I am trying to get the selected grade level and update the date fields accordingly _(not shown on this form, trying to strip this down for clarity) i.e._

'click #grade': function() {
    var getGrade = $('[name="grade"]').val();
    var aprDate = $("#apr").val();
    var iepDate = $("#iepdue").val();

    Session.set("grade", getGrade);
    Session.set("aprDate", aprDate);
    Session.set("iepDate", iepDate);

    if (getGrade === "Pre-Kindergarten") {
        var newIepDate = moment(aprDate).add(45, 'days').format("YYYY-MM-DD");
        document.getElementById('iepdue').value = newIepDate;
    } else {
        var newIepDate = moment(aprDate).add(60, 'days').format("YYYY-MM-DD");
        document.getElementById('iepdue').value = newIepDate;
    }

  },

So you want to modify other fields based on this value. Are these visible on this form? If so, use onChangeModel(model => { /* ... */ }) and update them or do not use AutoForm and keep the model by yourself (it was already discussed many times in other issues, try to search for them). If not, I guess it may be done once, in onSubmit.

The other fields are on the same form. I will give this a try and update the outcome, thank you!

Thank you, onChangeModel worked perfectly capturing all form updates. I was able to use onChange with conditions.

 <AutoForm
                ref={(ref) => { this.formRef = ref; }}
                schema={StuffSchema}
                onSubmit={this.submit}
                onChange={(key, value) => {
                    if (key === 'condition' && value === 'good') {
                        alert("Condition Good")
                } else {
                        alert("Condition Not Good")
                    }
                    console.log(key, value)} }
            >
Was this page helpful?
0 / 5 - 0 ratings

Related issues

simplecommerce picture simplecommerce  路  4Comments

thearabbit picture thearabbit  路  6Comments

Vandell63 picture Vandell63  路  3Comments

rafahoro picture rafahoro  路  3Comments

todda00 picture todda00  路  7Comments