0

I'm not 100% sure what I'm doing is correct. Basically I have a page which contains multiple components. One of the components, DynamicRequestorDetails, gets passed a list of possible components to be added to it (eg. textbox or dropdown). This one works and the textboxes/dropdowns are generated. My problem is the handleChange event of the parent container doesn't seem to get passed to the dynamic components generated by the componentHandler. Is there anything else I missed? I see the values are passed correctly but during debugging it seems like the handleChange event is not being triggered by the dynamically created components.

I have the following files:

Dropdown Component:

import React, {PropTypes} from 'react';

const Dropwdown = ({identifier, value, selectChanged, options, label}) => {    
    return (
        <div className="row eis-field-row">
            <label className="col-xs-4 TheSansBold">{label}</label>
            <select className="col-xs-6"
                name={identifier}
                id={identifier}
                onChange={selectChanged}
                value={value}
            >
                <option value="">--Please select one--</option>
                {
                options.map((option) => {
                    return <option key={option.Value} value={option.Value}>{option.Text}</option>;
                })
            }                
            </select>
        </div>
    );
};

Dropwdown.propTypes = {
    identifier: PropTypes.string,
    defaultOption: PropTypes.object,
    value: PropTypes.string,
    selectChanged: PropTypes.func,
    options: PropTypes.arrayOf(PropTypes.object),
    label: PropTypes.string

};

export default Dropwdown;

Component Handler:

import React from 'react';

/* import components here */
import Textbox from '../components/common/forms/Textbox';
import Dropdown from '../components/common/forms/Dropdown';

/* import component types */
import * as types from '../constants/FieldTypes';

export function getFieldValue(fieldValues, identifier) {
    let selectedItem = fieldValues.find(x => x.FieldID == identifier);
    if(Object.keys(selectedItem).length > 0) {
        return selectedItem.Value;
    }    
}

export function RenderComponent(field, handleChange, value) {
    switch(field.Type) {
        case types.TextComponent: {           
            return (
                <Textbox
                    type="text"
                    label={field.Label}
                    id={field.Identifier}
                    name={field.Identifier}
                    value={value}
                    onChange={handleChange}
                    placeholder={field.Placeholder}
                    key={field.Identifier}
                />
            );
        }

        case types.SelectComponent: {
            return (
                <Dropdown
                    name={field.Identifier}
                    label={field.Label}
                    id={field.Identifier}
                    onChange={handleChange}
                    value={value}
                    options={field.Options}
                    key={field.Identifier}
                />
            );
        }

        default: {
            return null;
        }
    }
}

DynamicRequestorDetails Component:

import React, {PropTypes} from 'react';
import * as ch from '../../utilites/componentHandler';

const DynamicRequestorDetails = ({userinfo, ccValue, handleChange, isVisible, customFields, fieldValues}) => {
    let wrapperClass = " hidden";
    if(!isVisible) {
        wrapperClass = "";
    } else {
        wrapperClass = " hidden";
    }

    return (
        <div>
            <label className="label-headers TheSansBold">REQUESTOR DETAILS</label>
            <div className="row eis-field-row">
                <label className="TheSansBold col-xs-4">Name</label>
                <label id="requestorName" className="col-xs-6 field-value">{userinfo.DisplayName}</label>
            </div>
            <div className="row eis-field-row">
                <label className="col-xs-4 TheSansBold ">Employee No</label>
                <label className="col-xs-6 field-value">{userinfo.LanId}</label>
            </div>
            <div className="row eis-field-row">
                <label className="col-xs-4 TheSansBold">Department</label>
                <label className="col-xs-6 field-value">{userinfo.Department}</label>
            </div>
            <div className="row eis-field-row">
                <label className="col-xs-4 TheSansBold">Designation</label>
                <label className="col-xs-6 field-value">{userinfo.Title}</label>
            </div>
            <div className="row eis-field-row">
                <label className="col-xs-4 TheSansBold">Contact No</label>
                <label className="col-xs-6 field-value">{userinfo.Mobile}</label>
            </div>
            <div id="reqDivsion" className={"row eis-field-row" + wrapperClass}>
                <label className="col-xs-4 TheSansBold">Divsion</label>
                <select className="col-xs-6" onChange={handleChange}>
                    <option value="1">--Select Division--</option>
                    <option value="2">Group 1</option>
                    <option value="3">Group 2</option>
                    <option value="4">Group 3</option>
                    <option value="5">Group 4</option>
                    <option value="6">Group 5</option>
                    <option value="7">Group 6</option>
                </select>
            </div>            
            <div className={"row eis-field-row" + wrapperClass}>
                <label className="col-xs-4 TheSansBold">Cost Center: </label>
                <input type="text" value={ccValue} onChange={handleChange} className="col-xs-6" />
            </div>
            {
                customFields.map(customField => {
                    let fieldValue = ch.getFieldValue(fieldValues, customField.Identifier);
                    return ch.RenderComponent(customField, handleChange, fieldValue);
                })
            }            
        </div>
    );
};

DynamicRequestorDetails.propTypes = {
    userinfo: PropTypes.object.isRequired,
    ccValue: PropTypes.string,
    handleChange: PropTypes.func,
    divChange: PropTypes.func,
    isVisible: PropTypes.bool,
    customFields: PropTypes.arrayOf(PropTypes.object),
    fieldValues: PropTypes.arrayOf(PropTypes.object)
};

export default DynamicRequestorDetails;

Parent Component:

const steps = def.ProcessPages[0].Steps;

class NewSMILEPage extends React.Component {
    constructor(props, context) {
        super(props, context);

        this.state = {
            FieldValues: []
        };

        this.handleChange = this.handleChange.bind(this);
        this.goBack = this.goBack.bind(this);
    }

    componentDidMount() {
        this.populateFieldValues();
    }

    componentWillReceiveProps(newProps) {
        if(newProps.smile.FieldValues != this.props.smile.FieldValues) {
            this.setState({FieldValues: newProps.smile.FieldValues});
        }
    }

    handleChange(e, identifier) {

    }

    populateFieldValues() {
        //populates values for my state
    }

    updateFieldValues(fv) {
        //updates values for my state
    }

    goBack() {
        //do some action
    }    

    render() {
        if(this.state.FieldValues.length > 0) {
            return (
                <div className="container-fluid">
                    <div className="row">
                        <div className="col-xs-4">
                            <FormHeader formName={this.props.eforms.SelectedEForm.Title} />
                        </div>
                        <div className="col-xs-8">
                            <StepTracker steps={def.ProcessPages[0].Steps} />
                        </div>
                    </div>
                    {/*Step Name and Image*/}
                    <div className="row form-label-container">
                        <img src={HeaderImage} alt="Header Image" width="40" className="pull-left"/>
                        <p className="form-header pull-left TheSansBold">NEW REQUEST</p>
                    </div>
                    <div className="row">
                        <div className="col-xs-6 pull-left">
                            <DynamicRequestorDetails
                                userinfo={this.props.userinfo}
                                isVisible={this.props.isVisible} 
                                ccValue=""
                                ccValueChange={this.handleChange}
                                divChange={this.divisionChange}
                                customFields={def.ProcessPages[0].Fields}
                                handleChange={this.handleChange}
                                fieldValues={this.state.FieldValues}
                            />
                        </div>
                    </div>
                    <div className="row footer-button-container footer">
                        <div className="pull-left">
                            <button id="btnBack" type="button" className="btn btn-back" onClick={this.goBack} >CANCEL</button>
                        </div>
                        <div className="pull-right">
                            <button id="btnNext" type="button" className="btn btn-next margin-right-lg" onClick={this.goNext}>NEXT</button>
                        </div>
                    </div>
                </div> 
            );
        } else {
            return (<h1>Loading</h1>);
        }
    }
}

function mapStateToProps(state, ownProps) {
    return {
        //state to props returned here      
    };
}

function mapDispatchToProps(dispatch) {
    return {
        //actions returned here
    };
}

NewSMILEPage.propTypes = {
    //prop checking done here
};

export default connect(mapStateToProps, mapDispatchToProps)(NewSMILEPage);

1 Answer 1

1

Parameter names mismatch selectChanged/handleChange, missing selectChanged...

You're using onChange on component in RenderComponent - it works like passing prop with that name, not assigning handler. onChange should be used in render on 'normal' html elements only.

Sign up to request clarification or add additional context in comments.

1 Comment

Than you so much! Sometimes I feel stupid asking these questions specially when I realize the answer. It looks simple but I usually miss items like these.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.