dscham
dscham

Reputation: 567

Why is this child object empty, whatever i do?

I'm scratching my head bleeding on this one.

Tried:

Reservation.insert(this.state);

const res = // Setting every field manually

const res = // Setting every field manually aswell as setting the parkingLot fields, as you can see in the code

I have not idea what else I could try, res.parkingLot always stays as an empty object. Which results in errors when trying to insert.

The full function is here:

handleSubmit(event, $) {
  event.preventDefault();

  const res = {
    date: new Date(),
    parkingLot: {
      _id: this.state.parkingLot._id,
      number: this.state.parkingLot.number,
      name: this.state.parkingLot.name,
      description: this.state.parkingLot.description,
      price: this.state.parkingLot.price,
      reserved: this.state.parkingLot.reserved,
    },
    user: $.state.user,
    begin: $.state.begin,
    end: $.state.end,
  };

  console.log('Submit', res, this.state);

  Reservation.insert(res);
}

I was asked to add my whole Code so:

ReservationForm.js

import React, {Component} from 'react';
import {Reservation} from "../../../shared/collections/Reservation";
import {withTracker} from "meteor/react-meteor-data";
import {ParkingLot} from "../../../shared/collections/ParkingLot";
import MaterialSelect from "../form/MaterialSelect";
import * as M from "materialize-css";

class ReservationForm extends Component {
    constructor(props) {
        super(props);
        this.state = {};

        this.handleInputChange = this.handleInputChange.bind(this);
        this.handleSubmit = this.handleSubmit.bind(this);
        this.handleBeginPicker = this.handleBeginPicker.bind(this);
        this.handleEndPicker = this.handleEndPicker.bind(this);
    }

    componentDidMount() {
        let beginPicker = document.querySelector('#begin');
        let endPicker = document.querySelector('#end');
        M.Datepicker.init(beginPicker, {
            autoClose: true,
            onSelect: this.handleBeginPicker
        });
        M.Datepicker.init(endPicker, {
            autoClose: true,
            onSelect: this.handleEndPicker
        });
    }

    handleBeginPicker(date) {
        const event = {
            target: {
                name: 'begin',
                value: date
            }
        };

        this.handleInputChange(event);
    }

    handleEndPicker(date) {
        const event = {
            target: {
                name: 'end',
                value: date
            }
        };

        this.handleInputChange(event);
    }

    handleInputChange(event) {
        const target = event.target;
        const value = target.type === 'checkbox' ? target.checked : target.value;
        const name = target.name;
        this.setState({
            [name]: value
        });
    }


    handleSubmit(event) {
        event.preventDefault();
        try {
            Reservation.insert(this.state, function(error) { error ? console.log( 'Insert Error', error) : null});
        } catch (e) {
            console.error(e);
            M.toast({
               html: e.reason,
            });
        }
    }

    render() {
        const $ = this;
        return (
            <div className="row">
                <h5>Reservierung anlegen</h5>
                <form className="col s6" onSubmit={this.handleSubmit}>
                    <div className="row">
                        <label htmlFor='parkingLot'>Parkplatz</label>
                        <MaterialSelect ided='parkingLot'
                                        named='parkingLot'
                                        labeled='Parkplatz'
                                        textField='name'
                                        valueField='_id'
                                        options={this.props.lots}
                                        placeholder='Parkplatz wählen'
                                        onChange={this.handleInputChange}/>
                    </div>
                    <div className="row input-field">
                        <input id='begin' name='begin' type='text' className='datepicker'
                               data-value={this.state.begin}/>
                        <label className='' htmlFor='begin'>Anfang</label>
                    </div>
                    <div className="row input-field">
                        <input id='end' name='end' type='text' className='datepicker'
                               data-value={this.state.end}/>
                        <label className='' htmlFor='end'>Ende</label>
                    </div>
                    <button className="btn waves-effect waves-light" type="submit" name="action"><i
                        className="material-icons right">create</i>Anlegen
                    </button>
                </form>
            </div>
        );
    }
}

export default withTracker(() => {
    Meteor.subscribe('parkingLots');
    return {
        lots: ParkingLot.find({}).fetch(),
    };
})(ReservationForm);

MaterialSelect.js

import React, {Component} from "react";
import {Random} from "meteor/random";
import * as M from "materialize-css";

export default class MaterialSelect extends Component {

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

    componentDidMount() {
        let select = document.querySelector(`#${this.props.ided}`);

        //M.FormSelect.init(select, {});
    }

    handleInputChange(event, $) {
        event.preventDefault();
        $.props.onChange(event);
        const target = event.target;
        const value = target.type === 'checkbox' ? target.checked : target.value;
        const name = target.name;

        this.setState({
            [name]: value
        });
    }

    render() {
        const options = this.props.options.map(option => {
            return <option value={!!this.props.valueField ? option[this.props.valueField] : option}
                           key={Random.id(4)}>{!!this.props.textField ? option[this.props.textField] : option}</option>
        });

        const $ = this;
        return (
                <select id={this.props.ided}
                        name={this.props.named}
                        defaultValue=''
                        value={this.state.value}
                        className='no-autoinit browser-default'
                        onChange={function(event) {$.handleInputChange(event, $)}} >
                    <option value="" disabled>{this.props.placeholder}</option>
                    <option value="crap value">Not Existing Value Test</option>
                    {options}
                </select>
        );
    }


}

Upvotes: 1

Views: 156

Answers (2)

Marco Hern&#225;ndez
Marco Hern&#225;ndez

Reputation: 305

Did you bind this in the component constructor?

class MyComponent extends React.Component {
  constructor(props) {
    super(props)

    this.handleSubmit = this.handleSubmit.bind(this)
  }

  handleSubmit(evt) {
   ...
  }
}

As an alternative, you can use class properties and declare your event handlers as arrow functions instead. For that you would need the babel plugin @babel/plugin-proposal-class-properties

Also take a look at: https://reactjs.org/docs/faq-functions.html

Upvotes: 0

Rotem Orbach
Rotem Orbach

Reputation: 142

I tried this:

 <script>
  const res = {
    date: new Date(),
    parkingLot: {
      _id: 11,
      number: 12,
      name: 'jhon',
      description: 'j',
      price: 3232,
      reserved: true,
    },
    user: 'j',
    begin: 'j',
    end: 'j',
  };

console.log(res);
</script>

and it works perfectly. Are you sure all the properties are actually there? try to debug it in the console. Does "this.state.parkingLot._id" actually returns a number?

Upvotes: 0

Related Questions