Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Traversing children's children and adding function to all inputs while keep other children untouched

I have been trying to get this to work for a while now and not sure how to do the following. My form component has children that contain regular html markup as well a inputs. If the child is a Input I want to add the attachToForm and detachFromForm functions. If it is not an input I want to continue traversing the children to make sure that the element does not have a child input field. Wether or not the element is an input I still want it to appear on my page, I just want to add the functions to the inputs.

The problem is I can only get my function to return only the inputs, removing the labels and title. I know that is because Im only adding elements with inputs to newChildren, but if I push the other elements in the else if section I get duplicates and i can think of another way of doing this. Im not sure if im not understanding basic JS or having a brain gap.

React.Children.forEach(children, function(child) {
        var current = child;
        if (child.props && child.props.name) {
            this.newChildren.push(React.cloneElement(child, {
                detachFromForm: this.detachFromForm,
                attachToForm: this.attachToForm,
                key: child.props.name
            }));
        } else if (child.props && child.props.children){
            this.newChildren.push(child);
            this.registerInputs(child.props.children);
        } else {
            *need to keep track of parent elements and elements that do not have inputs
        }
    }.bind(this));

Edit: Not sure if needed but this is and example form im traversing

return ( 
            <Modal className="_common-edit-team-settings" title={`Edit ${this.props.team.name}`} isOpen={this.props.modalIsOpen && this.props.editTeamModal} onCancel={this.props.toggleEditTeamModal} backdropClosesModal>

                <Form onSubmit={this.saveChanges}>      
                    <FormSection className="edit-team-details" sectionHeader="Team Details">
                        <FormField label="Name">
                            <Input name="name" value={this.state.values.name} onChange={this.handleInputChange} type="text" placeholder={this.props.team.name}/>
                        </FormField>
                        <FormField label="Mission">
                            <Input name="mission" value={this.state.values.mission} onChange={this.handleInputChange} type="text" placeholder={this.props.team.kitMission || 'Kit Mission'} multiline />
                        </FormField>
                    </FormSection>

                    <FormSection className="privacy-settings" sectionHeader="Privacy Settings">
                        <FormField label="Included in global search results" >
                            <SlideToggle name="globalSearch" defaultChecked={this.state.values.globalSearch} onChange={this.handleCheckedChange} type="checkbox" />
                        </FormField>
                        <FormField label="Accessible by anyone" >
                            <SlideToggle name="public" defaultChecked={this.state.values.public} onChange={this.handleCheckedChange} type="checkbox" />
                        </FormField>
                        <FormField label="Secured with WitCrypt" >
                            <SlideToggle name="witcryptSecured" defaultChecked={this.state.values.witcryptSecured} onChange={this.handleCheckedChange} type="checkbox" />
                        </FormField>
                    </FormSection>
                    <FormSection sectionHeader="Participants">
                        {participantsList}
                        <div id="add-participant" className="participant" onClick={this.toggleAddParticipantModal}>
                            <span className="participant-avatar" style={{backgroundImage:'url(/img/blue_add.svg)'}}></span>
                            <span>Add a Participant</span>
                            <span className="add-action roll"><a></a></span>
                        </div>
                    </FormSection>
                    <Button type="hollow-primary" size="md" className="single-modal-btn" block submit>Save</Button>
                </Form>


                <AddParticipant people={this.props.people} toggleAddParticipantModal={this.props.toggleAddParticipantModal} modalIsOpen={this.props.modalIsOpen} toggleAddParticipantModal={this.toggleAddParticipantModal} addParticipantModal={this.state.addParticipantModal} />
            </Modal>
        );

As an aside I started out a lot simpler wanting to do the following but get:

"Can't add property attachToForm, object is not extensible"

If anyone knows why please let me know.

registerInputs: function (children) {

    React.Children.forEach(children, function (child) {

      if (child.props.name) {

        child.props.attachToForm = this.attachToForm;
        child.props.detachFromForm = this.detachFromForm;
      }

      if (child.props.children) {
        this.registerInputs(child.props.children);
      }
    }.bind(this));
  }
like image 571
ReganPerkins Avatar asked Nov 13 '15 22:11

ReganPerkins


1 Answers

Judging of an error message, you have a problem with immutable prop object. Starting from React 0.14 the prop is "frozen":

The props object is now frozen, so mutating props after creating a component element is no longer supported. In most cases, React.cloneElement should be used instead. This change makes your components easier to reason about and enables the compiler optimizations mentioned above.

Blog post on this

So somewhere in your code you try to extend a prop object causing an error.

You could wrap different parts of your prop interactions with try..catch construction which will point you the exact problem place.

like image 135
Eugene Tiurin Avatar answered Nov 15 '22 14:11

Eugene Tiurin