1

I am creating a react app i have to add an input toggle inside my header component. I tried to add but JavaScript is not working. if

this is the header component file. inside this component I have included my input toggle condition. i have placed JavaScript code right below the imports.

anyone knows please check thanks..

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import {
  Nav,
  Navbar,
  Collapse,
  DropdownMenu,
  DropdownItem,
  NavbarToggler,
  DropdownToggle,
  UncontrolledDropdown,
} from 'reactstrap';
import { Link, withRouter } from 'react-router-dom';
import Config from '../../../constants/config';
import { SidebarNavItems } from '../Sidebar';
import logoImages from '../../../images/logo.png';
require('./styles.scss');

var allInputs = document.querySelectorAll('.myInput');
allInputs.forEach(function(node) {
    node.addEventListener("click", function(){
      var allHiddenInputs = document.querySelectorAll('.hidden');
      if(allHiddenInputs.length === 0) {
        allInputs.forEach(function(input) {
          input.classList.add("hidden");
          input.classList.add("second");
          input.classList.remove("first");
        });
        node.classList.remove("hidden");
        node.classList.remove("second");
        node.classList.add("first");
      } else {
        allHiddenInputs.forEach(function(input) {
          input.classList.remove("hidden");
        });
      }
    });
});
class Search extends Component {
  constructor(props) {
    super(props);
  }

  render() {

    return (
      <div className="">
        <div className="input-container">
          <input type="password" placeholder="Input 1" className="myInput first" />
          <input type="password" placeholder="Input 2" className="myInput second hidden" />
        </div>
      </div>

    );
  }
}

export default withRouter(Search);

this is my css file which linked to this component.

.input-container {
  display: flex;
  flex-direction: column;
}
.myInput {
  margin: 10px;
  padding: 5px
}
.first {
  order: 1;
}
.second {
  order: 2;
}
.hidden {
  display: none;
}

enter image description here

fhei izze
  • 81
  • 2
  • 11
  • when you import this file the JS code will run. you probably dont want to use all of these dom selectors unless you have to. It looks like the js code at the top is trying to make changes to the html rendered in your component? So you should instead change classes on the component inside the component. And probably use state to handle the toggle – John Ruddell Aug 09 '18 at 04:04
  • @JohnRuddell thanks for the reply.I'll try that way thanks again. if possible can you please provide a solution as an answer ? – fhei izze Aug 09 '18 at 04:11
  • yes i'd be happy to. before i do though can you clarify what your JS code is supposed to be doing? it looks like when you click on an input you then hide that input and show a different one? what is the purpose of that behavior? – John Ruddell Aug 09 '18 at 04:13
  • thanks again for reply .actually its a search bar , there are 2 types of search so 1 input is for type 1 and second input is for other type of search. so when you click each search it will toggle between each https://codepen.io/feizel/pen/OwBQPy it wil be like this in website – fhei izze Aug 09 '18 at 04:18
  • just wrote up an answer real quick that does what you want :) let me know if you have any questions – John Ruddell Aug 09 '18 at 05:03

4 Answers4

2

What I would do to simulate the same thing as you are trying to do would be to use local state to update the view. You can conditionally render items as well as class names for each render cycle.

class App extends React.Component {
    constructor() {
      super()
      this.inputNames = ['input1', 'input2']
      this.state = {
        hiddenInputs: {
        input1: { hidden: false, first: true },
        input2: { hidden: true, first: false }
      },
      expanded: false
    }
  }
  handleClick(name) {
    const hI = Object.assign({}, this.state.hiddenInputs)
    let expanded = this.state.expanded

    if (expanded && hI[name].first === true) {
      // clicked on the first element, we hide the other
      expanded = false
    } else if (expanded) {
        // clicked on non first item, change order
      this.inputNames.forEach(input => {
        const isSame = input === name
        hI[input].first = isSame
        hI[input].hidden = !isSame
      })
    } else {
        // its not open yet, show the other
        expanded = true
    }

    this.setState({expanded, hiddenInputs: hI})
  }
  render() {
    const { input1, input2 } = this.state.hiddenInputs
    const {expanded} = this.state
    const clsName1 = `myInput${input1.hidden && !expanded ? ' hidden' : ''}${input1.first ? ' first' : ' second'}`;
    const clsName2 = `myInput${input2.hidden && !expanded ? ' hidden' : ''}${input2.first ? ' first' : ' second'}`;
    return (
        <div className="">
        <div className="input-container flex">
          <input type="password" placeholder="Input 1" onClick={this.handleClick.bind(this, 'input1')} className={clsName1} />
          <input type="password" placeholder="Input 2" onClick={this.handleClick.bind(this, 'input2')}  className={clsName2} />
        </div>
      </div>
    );
  }
}

ReactDOM.render(
  <App />,
  document.getElementById('container')
);

CSS:

.flex {
  display: flex;
}
.first {
  order: 0;
}
.second {
  order: 1;
}
.hidden {
  display: none;
}

Fiddle to see it in action

John Ruddell
  • 25,283
  • 6
  • 57
  • 86
  • this is what I was expecting thanks , and small thing now when we click the right side input it switch with left side input is it possible when we click right side input hide the left side toggle instead of switching – fhei izze Aug 09 '18 at 05:11
  • thanks, not sure what you mean. what does click right side input? like a part of the input or just the input? like `input1`.. are you asking if clicking the right side of `input1` we do something or clicking on `input1` when its the second input? – John Ruddell Aug 09 '18 at 05:14
  • It works exactly how it did in that codepen you showed me – John Ruddell Aug 09 '18 at 05:22
  • sorry my mistake i send the wrong codepen link, at first , im really sorry when you click the down 1 in code pen it hides top 1 but here it only switches the inputs its not hiding the top1 – fhei izze Aug 09 '18 at 05:24
  • ok thats a different codepen than this one codepen.io/feizel/pen/OwBQPy .. but sure just look at the code. theres a state for expanded. you just need to toggle it when you switch the items. do you need me to do that for you? or can you figure it out – John Ruddell Aug 09 '18 at 05:26
  • thanks .I tried but could not figure out how to do it , if possible can you please do it , – fhei izze Aug 09 '18 at 05:34
  • just add `expanded = false` to the first else if.. the one with the comment `// clicked on non first item, change order` – John Ruddell Aug 09 '18 at 05:42
1

Try to put your code to component lifecycle (like a componentDidMount), then it would work. But in react it is not good solution to work with DOM nodes directly. Better way would be to make like that:

class Search extends Component {
  constructor(props) {
    super(props);
    this.state = {allInputsHidden: true}; // You can change it later
  }

  render() {

    return (
      <div className="">
        <div className="input-container">
          <input type="password" placeholder="Input 1" className="myInput first" />
          <input type="password" placeholder="Input 2" className={this.state.allInputsHidden ? "myInput second hidden" : "myInput second"} />
        </div>
      </div>

    );
  }
}

Also, you can use package classnames to make it look more pretty

Klimenko Kirill
  • 634
  • 2
  • 8
  • 22
1

Use conditional rendering to achieve this task. You can refer this page. Create your input group as a component and add a boolean prop to use with if condition. This is much better than adding classes.

function Inputs(props) {
  const isFirst = props.isFirst;
  if (isFirst) {
    return <input type="password" placeholder="Input 1" className="myInput first" />;
  }
  return <input type="password" placeholder="Input 2" className="myInput second" />;
}

ReactDOM.render(
  <Inputs isFirst={true} />,
  document.getElementById('root')
);

And add a click event to toggle the value of isFirst variable.

anjuc
  • 159
  • 2
  • 10
1

You may use state to decide which element to be displayed ...

   class Search extends Component {
             constructor(props) {
             super(props);
             this.state = {
             toggleInput1:true,

              }

      render() {

    return (
      <div className="">
        <div className="input-container">
         {this.state.toggleInput1?
          <input type="password" placeholder="Input 1" className="myInput 
           first" />: 
          <input type="password" placeholder="Input 2" className="myInput 
          second hidden" />
     }
        </div>
      </div>

    );
     }
    }

    export default withRouter(Search);

And On EventListener change the state of toogleInput

handleClick = event => {
    this.setState({toggleInput1:!this.state.toggleInput1 });
  };
Sanjay A
  • 316
  • 3
  • 15
  • you mean I have to add this in a separate component and call it inside main component ? – fhei izze Aug 09 '18 at 04:13
  • It would be going in same component ... on the event which the toggle need to achieved ... onClick={event => this.handleClick(event)}.. you may keep on both input tag and check – Sanjay A Aug 09 '18 at 04:17
  • Im expecting somthing like this bro, the click event also would be for input only please check this codepen link https://codepen.io/feizel/pen/OwBQPy – fhei izze Aug 09 '18 at 04:56