React input focus event to display other component - javascript

I was read some tutorial about this. They told me should using ref to do that.
But It's very general.
Here is my problem:
Basically in Header component include NavBar, SearchBar and ResultSearch component.
const Header = () => {
return (
<header className="ss_header">
<Navbar />
<SearchBar />
<ResultSearch />
</header>
);
};
And In SearchBar component. Whenever I focused on input text. It emit an event and display ResultSearch component by any way (changing style, or ...).
class SearchBar extends Component{
render() {
return (
<div className="search_bar">
<section className="search">
<div className="sub_media container">
<form method="GET" action="" id="search_form">
<Icon icon="search" />
<span className="autocomplete">
<input
className="search_input"
autoCorrect="off"
autoComplete="off"
name="query"
type="text"
placeholder="Search for a movie, tv show, person..." />
</span>
</form>
</div>
</section>
</div>
);
}
}
Style in ResultSearch component. I was set display: none.
.results_search { display: none; }
I think ResultSearch will receive an event from SearchBar and set back display: block for ResultSearch component. Is possible?
How can I handle that?
My Code here: https://codesandbox.io/s/3xv8xnx3z5

only you should convert Header component like following:
class Header extends Component {
state = {
focus: false
};
handleInputFocus = () => {
this.setState({ focus: true });
};
handleInputBlur = () => {
this.setState({ focus: false });
};
render() {
return (
<header className="ss_header">
<SearchBar
onFocus={this.handleInputFocus}
onBlur={this.handleInputBlur}
/>
{this.state.focus ? <ResultSearch /> : null}
</header>
);
}
}
and also in SearchBar component add following attributes to your input:
onFocus={this.props.onFocus}
onBlur={this.props.onBlur}
also, you should remove your CSS about result box.
And, you can see the updated code on the following sandbox:
https://codesandbox.io/s/mmj46xkpo9

Still not sure what you're trying to achieve.
This is the way you can handle visibility of result of the search. Let me know if this isn't what you're looking for.
https://codesandbox.io/s/7jvz31xr66

Related

React Button Click should change the display value of div

I got a Navbar which has a button do change the display value of a login form. The Login form and the Login form is a diffrent file, the navbar is a diffrent file and the homepage where it should be display is a diffrent file. Those are the minimal variants of each so that you got some got to understand my problem in detail:
Homepage:
const HomePage = () => {
return (
<div>
<Navbar />
<Login />
<div id="content">
</div>
</div>
);
}
Navbar:
const Navbar= () => {
const showLogin = () => {
document.getElementById('Login').style.display='block';
}
return (
<div id="Navbar">
<NavLink activeClassName="active" to='/'><img src={logo}/></NavLink>
<ul>
...
</ul>
<ul>
<button onClick={showLogin}>Anmelden</button>
</ul>
</div>
);
}
Login-Form:
const Login = () => {
return (
<div id="Login">
<form>
<label>Anmelden</label>
<label for="username">Nutzername</label>
<input name="username" type="text"></input>
<label for="pw">Passwort</label>
<input name="pw" type="password"></input>
<button type="submit">Login</button>
</form>
</div>
);
}
Is there a way to achieve this, or would my easiest option be to include the Login source code into the Navbar source code?
You do not need to move your Login component inside Navbar. Keep it as it is.
You can use useState and Props to switch css classes to show/hide your Login component. I have created very simple solution for you in this CodeSandbox.
Steps:
Create two CSS classes hidden and block
In your Login component add a boolean prop which switches class hidden to block if true.
Create a prop for onClick in the Login component.
Create a useState inside your Homepage which holds a boolean value. That boolean value pass it to the Login page prop and then use onClick prop from Navbar to switch that boolean state
Yes, depending on your CSS system this is easily achievable just by using that.
The React solution is using refs.
The easy way is to create a ref in the parent component and then pass it down as a prop to both components:
In Homepage (i.e. parent), create a ref like so loginRef = useRef(); then pass it down as a prop to the 2 children.
In Login-Form.js you assign that prop on the div with id Login like so <div id='Login' ref={props.loginRef}>
Then in Navbar.js you can use that prop to change its display value like so const showLogin = () => {props.loginRef.current.style.display='block';}
NB: This is a fast and easy way, not best practice but it gets the work done. The best-practice here is to use forwardRef and - super advanced - useImperativeHandle. Take your time and go through the documentation when you're ready.
Login page will show "it is not active" first because active is set to false.but once you click on submit button it will show "it is active"
HomePage
const HomePage = () => {
const[active,setActive]=useState(false);
return (
<div>
<Navbar activesetter={setActive} />
<Login activestatus={active} />
<div id="content">
</div>
</div>
);
}
Login
const Login = (props) => {
return(
<div>
<div>
{props.activestatus ? "it is active" : "it is not active" }
</div>
</div>
);
}
Navbar
const Navbar = (props) => {
const handleSubmit=(e)=> {
e.preventDefault();
props.activesetter(true);
}
return(
<div>
<form onSubmit={handleSubmit}>
<button type="submit">Login</button>
</form>
</div>
);
}

Show Component inside a Collapsible

Hello I'm trying to show a Form Component inside an 'antd' Collapsible when the user clicks on the form icon the Form Component should appear inside the Collapsible below the text that's already there
I'm using the antd library for the Collapsible
import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import { Collapse, Icon } from 'antd';
import Form from './Form';
const { Panel } = Collapse;
const text = `
A dog is a type of domesticated animal.
Known for its loyalty and faithfulness,
it can be found as a welcome guest in many households across the world.
`;
const genExtra = () => (
<Icon
type="form"
onClick={event => {
// If you don't want click extra trigger collapse, you can prevent this:
event.stopPropagation();
console.log('You have click on edit form');
}}
/>
);
const customPanelStyle = {
background: '#f7f7f7',
borderRadius: 4,
marginBottom: 24,
border: 0,
overflow: 'hidden',
};
ReactDOM.render(
<Collapse
bordered={false}
defaultActiveKey={['1']}
expandIcon={({ isActive }) => <Icon type="caret-right" rotate={isActive ? 90 : 0} />}
>
<Panel
header="This is panel header 1"
key="1" style={customPanelStyle}
extra={genExtra()}
>
<p>{text}</p>
</Panel>
</Collapse>,
document.getElementById('container'),
);
this is the Form Component:
import React from 'react';
const Form = () => {
return(
<div id="wrapper">
<div className="group">
<label for="name">Name</label>
<input type="text" id="name" />
</div>
<hr/>
<div className="group">
<label for="email">Email</label>
<input type="email" id="email" />
</div>
</div>
);
}
export default Form;
--
I just want the Form Component to appear inside the collapsible when the user clicks on the little icon in the header I'll leave a link to the stackblitz: https://stackblitz.com/edit/react-pkffgm
You need to move your Collapsible to another class based component, where you can have state to show / hide your Form component,
In newly constructed class based component you need to maintain state like,
constructor(props){
super(props);
this.state ={
showForm: false
}
}
Then in render you can show your Form like this,
<Panel
header="This is panel header 1"
key="1" style={customPanelStyle}
extra={this.genExtra()}
>
<p>{text}</p>
{this.state.showForm && <Form />}
</Panel>
And finally on click of form edit icon you need to change state of showForm like,
genExtra = () => (
<Icon
type="form"
onClick={event => {
// If you don't want click extra trigger collapse, you can prevent this:
event.stopPropagation();
this.setState({showForm: true})
console.log('You have click on edit form');
}}
/>
);
Note: In the Form component you are getting warning for your lable,
<label htmlFor="name">Name</label> //instead of `for` attribute in react we have `htmlFor` attribute.
Demo

Input Box problem In reactjs, On single click cursor is not pointing in text-box , On double click in the text-box Input Cursor is coming

I am very new to this. Below is the code, please Help
On single click Input cursor is not pointing in text-box, On double click on the text-box Input Cursor is coming. Also if I am adding a placeholder, not able to input anything.
export default class Login extends Component {
state = {
UserID: "",
Password: ""
};
UserIdchangeHandler = text => {
this.setState({
UserID: text.target.value
});
};
PasswordchangeHandler = text => {
this.setState({
Password: text.target.value
});
};
render() {
return (
<div className="backgroundImg">
<span>
<FontAwesomeIcon icon={faUserTie} size="lg" />
</span>
<input
type="text"
onChange={text => {
this.UserIdchangeHandler(text);
}}
/>
<br />
<span>
<FontAwesomeIcon icon={faKey} size="lg" />
</span>
<input
type="password"
onChange={text => {
this.UserIdchangeHandler(text);
}}
/>
<br />
<button>Login</button>
</div>
);
}
}
What is happening is that you have onChange handler but didn't set the value in your input.
If you add a onChange handler you need to add the value prop
<input
type="text"
value={this.stateUserId} // You're missing this here
onChange={evt => {
this.UserIdchangeHandler(evt);
}}
/>
You can learn more about controlled/uncontrolled on the React Docs here. In your case you're trying to create a controlled input
https://reactjs.org/docs/forms.html#controlled-components
Side Note:
In your onChange you labeled the property text. But its better to call it event
<input
type="text"
value={this.state.UserID} // you are missing value here.
onChange={text => {
this.UserIdchangeHandler(text);
}
}
/>
and same as the password input field.
import React, {Component} from 'react';
import "./login.css";
import { library, text } from '#fortawesome/fontawesome-svg-core'
import { FontAwesomeIcon } from '#fortawesome/react-fontawesome'
import { faUserTie, faKey, } from '#fortawesome/free-solid-svg-icons'
library.add(faUserTie)
export default class Login extends Component{
state={
UserID:"",
Password:""
}
UserIdchangeHandler=(text)=>{
this.setState({
UserID:text.target.value
})
}
PasswordchangeHandler=(pass)=>{
this.setState({
Password:pass.target.value
})
}
render() {
return (
<div className="backgroundImg">
<span>
<FontAwesomeIcon icon={faUserTie} size="lg"></FontAwesomeIcon>
</span>
<input type="text" onChange={(text)=>{this.UserIdchangeHandler(text)}} ></input>
<br/>
<span>
<FontAwesomeIcon icon={faKey} size="lg"></FontAwesomeIcon>
</span>
<input type="password" onChange={(pass)=>{this.PasswordchangeHandler(pass)}}></input>
<br/>
<button>Login</button>
</div>
);
}
}
Issue is resolved now. The problem was with Css of the class. Z-index was set to lower value.Increasing the z-index helped me here.

How to totally disable a react component?

I have a react component which has some buttons and text inputs. I want to totally disable all the things inside this component until some other works are complete. How to make the entire inner component disabled?
You can add disabled props and use CSS to disable div
const MyComponent = ({disabled}) => {
return (
<div style={disabled ? {pointerEvents: "none", opacity: "0.4"} : {}}>
<h1> Text</h1>
<input type="text"/>
<input type="password"/>
<button>Login</button>
</div>
)
}
Better to use form and fieldset, and put all the input/button elements inside that. You can disable all of them by setting the property disabled to fieldset.
Refer MDN Doc for more details.
Working example:
class App extends React.Component {
constructor () {
super()
this.state = { disable: false }
}
toggleDisable = () => this.setState(prevState => ({disable: !prevState.disable}))
buttonClick = (e) => {
e.preventDefault();
console.log('button clicked');
}
render (){
return (
<div>
<button className='toggle' onClick={this.toggleDisable}>Toggle Disable</button>
<form>
<fieldset disabled={this.state.disable}>
<input />
<button onClick={this.buttonClick}>Button</button>
</fieldset>
</form>
</div>
)
}
}
ReactDOM.render(<App />, document.getElementById('app'))
.toggle {
margin-bottom: 20px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id='app' />
All you need to do is add a disabled prop on the component and pass it on to the inner fields like
<MyComponent disabled={shouldComponentBeDisabled} {...otherProps} />
and in implementation
const MyComponent = ({disabled}) => {
return <div>
<button disabled={disabled}>someBtn</button>
<input type="text" disabled={disabled}/>
</div>
}
You can use disabled prop pattern to save the day.
const App = () => {
return (
<div>
<SomeComponent disabled />
</div>
);
};
const SomeComponent = ({ disabled = false }) => {
return (
!disabled && (
<div>
<h2>Disable SomeComponent to see magic happen!</h2>
</div>
)
);
};

Another case of React CSS Transitions not applying classes

I am trying to get my React CSS Transition classes applied to my DOM elements. I have done all of the following:
Referenced this question, to check correct use case and this other question making sure I am using a key attribute even when rendering one child.
If I am understanding correctly the library has migrated and the way we import the library is a little different, but let's look at what I'm working with.
Relevant code:
import {CSSTransitionGroup} from "react-transition-group";
class NewTournament extends React.Component{
render(){
const style = {
active: { display: "flex", flex: 5 },
inactive: null
}
const dynamic = this.props.editTournament != null ? style.active : style.inactive
return(
<div className="left-column">
<div className="tournament-creator">
<div id="banner">
<h1>Build A Tournament Here</h1>
</div>
<form action="" className="tournamentBuilder">
<input type="text" placeholder="Tournament Name" ref="nameRef" onChange={() => this.recordName()}/>
<input type="number" defaultValue={prelims} ref="prelimRef" onChange={() => this.updatePrelims()} />
<input type="number" defaultValue={outRounds} ref="outRoundRef" onChange={() => this.updateOutround()}/>
<input type="text" placeholder="Notes" ref="notesRef" onChange={() => this.recordNote()}/>
</form>
<div id="submitButton" onClick={() => this.createTournament()}>
Create Tournament
</div>
</div>
<CSSTransitionGroup className="tournament-editor"
component="div"
transitionName="editBoxRail"
transitionEnterTimeout={10000}
transitionLeaveTimeout={10000}
style={dynamic}>
<TournamentEditor key="editor" />
</CSSTransitionGroup>
</div>
)
}
}
So you click a button in the UI and then the tournament editor component goes from display: none to display: flex. It is my understanding that this will trigger the classes to be applied and taken away, but they are never applied the only way I have been successful in doing so is adding the transitionAppear={true} attribute where they just sit there and never go away.
What am I not doing correctly? This has me stumped because I've successfully worked with the older library and I don't know why this is giving me so much trouble.

Categories

Resources