:focus issues with React - javascript

I'm relatively new with ReactJS and I'm trying to implement a small form that contains an input text field and a search button. I'm using the :focus pseudo-selector on the input field so when the user enters information it increases the width to 2000% and when the element loses focus it goes back to width:130%.
The problem I'm having is when I click my search button for the first time the input field shrinks back to the original position but it doesn't do the search until I click it for the second time. If I type something and then click somewhere else to loose focus it works like a charm.
Here's my code:
import React from 'react'
import Header from '../base/header'
import axios from 'axios'
import SearchResults from './searchResults'
import ReactCSSTransitionGroup from 'react-addons-css-transition-group';
import Radium from 'radium';
class Search extends React.Component {
constructor(props) {
super(props)
this.state = {
searchTerm: "",
searchResultsList: ""
}
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
this.handleCallback = this.handleCallback.bind(this);
}
handleCallback() {
console.log("calling handleSubmit");
}
handleSubmit() {
var that = this
event.preventDefault();
axios.post('http://localhost:3000/users/findusers', {
searchTerm: this.state.searchTerm
}).then(function (response) {
console.log("data sent");
that.setState({searchResultsList: response.data})
}).catch(function (error) {
console.log(error);
});
}
handleChange(e) {
this.setState({searchTerm: e.target.value}, () => {
console.log(this.state.searchTerm);
});
}
render() {
return (
<div>
<Header/>
<form onSubmit={this.handleSubmit}>
<div>
<ReactCSSTransitionGroup
transitionName="search-input"
transitionAppear={true}
transitionAppearTimeout={500}
transitionEnter={false}
transitionLeave={false}>
<input
type="text"
style={styles.inputStyle}
value={this.state.searchTerm}
onChange={this.handleChange}
placeholder="Find Friends..."
/>
{/*<img onClick={() => this.handleSubmit()} */}
<img src="/icons/svg/magnifying-glass.svg"
alt="Search" className="searchIcon"
onClick={() => this.handleCallback()}
/>
</ReactCSSTransitionGroup>
</div>
</form>
<div className="container-fluid">
<div className="row">
<div className="col-md-3">left</div>
{/* Main Area */}
<div className="col-md-6">
<SearchResults
searchResultsList={this.state.searchResultsList}
/>
</div>
<div className="col-md-3">right</div>
</div>
</div>
</div>
)
}
}
const styles = {
inputStyle: {
marginTop: 5,
marginLeft: 20,
width: 130,
WebkitTransition: 'width 0.4s easeInOut',
msTransition: 'width 0.4s easeInOut',
':focus': {
width: '2000%'
}
}
};
export default Radium(Search)
I originally had the code in a separate CSS file and decided to make it inline to see if there was any difference. I tried creating different functions to see if there was any difference but is still behaving the same.
I would really appreciate any help!

In regards to the width changing when clicking the magnifying glass. I believe it is because the :focus property is on the input and not the div containing the input and img.
I would recommend using the :focus-within property on the parent div. Here is an example of divs with both properties.
#div1:focus-within > input {
width: 300px;
}
#div2 > input:focus {
width: 300px;
}
<div id="div1">
<input type="text"/>
<button>Search</button>
</div>
<div id="div2">
<input type="text"/>
<button>Search</button>
</div>
This should solve the focusing issue.
Not sure why your magnifying glass image works so strangely. When reading the code it seems that clicking the image calls handleCallback() which is only logging not submitting.
Not sure if this helps but I would recommend using a button or input element for submission. The button would have type="submit" with the magnifying glass image as the child. The input would have type="submit" value="" and set the CSS background-image: to the magnifying glass.

Related

React Bootstrap Overwrite Color of Form on Hover/Click

I'm trying to overwrite the color of a React-Bootstrap Form component. I'd like the background color to be of hex #44494f instead of the default blue in this image:
Now here's my code- I've tried editing the search-bar class via background-color, border-color, or color but none of them seem to work:
export const Markets = () => {
return (
<Form className="search-bar">
<Form.Control
placeholder="Search Markets"
onChange={(e) => setSearch(e.target.value)}
/>
</Form>
);
};
try doing this,
.search-bar {
background-color: #44494f !important;
}
or
<Form className="search-bar" style="background-color: #44494f">

How to add styles to a React component? [duplicate]

Currently I'm using react.js and I'm trying to get two div's to be side by side.
Currently I'm trying to
<div id="sidebar" style = "display:inline-block;" >
<script src="build/sidebar.js"></script>
</div>
<div id="map-canvas" style="display: inline-block; width: 20%; height: 50%; "></div>
with sidebar.js as the where react is stored. This unfortunately doesnt work however as it just moves map-canvas to the side while sidebar isn't to the left of it; its on top. I've tried many various combinations w/ float as well and none of them seem to work
Another option is to edit the sidebar.js code where I currently have
return <div>
<input type="text" value={this.state.searchString} onChange={this.handleChange} placeholder="Type here" />
<ul>
{ libraries.map(function(l){
return <li>{l.name} </li>
}) }
</ul>
</div>;
in which I try doing return <div style ="display: inline-block;">
However, in this case the generated html doesnt show up at all. I'm perplex to what I should try but react seems like it doesnt want to play nice with other div elements.
That's because in React, the style prop takes an object instead of a semicolon-separated string.
<div id="sidebar" style={{display : 'inline-block'}} >
<script src="build/sidebar.js"></script>
</div>
<div id="map-canvas" style={{display: 'inline-block', width: '20%', height: '50%'}}>
</div>
Edit:
So this:
return <div style="display: inline-block;">
Would become this:
return <div style={{display: 'inline-block'}}>
const styles = {
container: {
backgroundColor: '#ff9900',
...
...
textAlign: 'center'
}
}
export default class App extends React.Component {
render() {
return(
<div className="container" style={styles.container}>
// your other codes here...
</div>
);
}
}

Filter issue while using Search/Filter logic - React Native

I am struggling with my React Native App!!!!
I have a simple Flatlist.
I have a TextInput that has a filter option.
Click inside the TextInput. A dropdown of filter appears.
Click on that Filter it appears inside the TextInput.
Need some help in styling this!!! It should look somewhat like this. If not to this extent at least a box around it is fine.
I tried it with a Button - React Native elements. It's so so so frustrating. I cannot use any 3rd party libraries (company policy).
TextInput Code:
<Icon type='materialicons' name='search' /> // search icon
<Button icon={<Icon name="check"/>}. //my attempt to create a button around the filter
type='clear' title ={val}
onPress={()=>{this.handleFilterIcon(false); this.setFilt(false)}}/>
<TextInput // Text Input
value={value}
placeholder='Search Here...'
onChangeText={(text)=>{this.handleSearch(text, true);this.renderDropDown(false)}}
onTouchStart={()=>{this.setTempNotifications();this.renderDropDown(true)}}
style={{ height: 40, flex: 1}}
autoCapitalize='none'
selectTextOnFocus={true}
label='input'
/>
<Icon type='materialicons' name='cancel' onPress={()=>{} /> // Clear Icon
<Button title='Cancel'
buttonStyle={{backgroundColor:'#D3D3D3', borderColor: 'grey', borderRadius: 6 , borderWidth: 1, height: 40}}
onPress={()=>{} /> // Cancel button
Anyone please tell me the most efficient way to do this!!!
The only way I'm seeing is, since you don't have to use third party libraries is this:
Create a an empty label next to the input. Wrap these two with a div with position:relative
As soon as input is entered, put the same text in this label. Customise this label with styling: position:absolute;background:grey...
Just to give you some idea, here's an implementation in JQuery. You have to take this forward and ask specific question where you're struggling.
function inputChange(val){
$('label').text(val);
$('input').val("");
}
label{
border:1px solid;
border-radius: 5px;
position: absolute;
background: grey;
left:2px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div>
<input type="text" onchange="inputChange(this.value)"/>
<label></label>
</div>
In React the same implementation could look something like this. You can create a file with this implementation, import in your App.js and see. Take this idea fowrward and change the styling and behaviours as per the need.
import React, { Component } from 'react';
class CustomInputTextstyling extends Component {
constructor(props) {
super(props);
this.state ={
inputText: ""
}
}
handleInputChange(e){
this.setState({inputText: e.target.value});
}
render() {
const wrapperDiv = {
position: 'relative'
}
const label = {
border:'1px solid',
borderRadius: '5px',
position: 'absolute',
background: 'grey',
left:'2px'
}
return (
<div style={wrapperDiv}>
<input type = "text" onBlur = {this.handleInputChange.bind(this)}></input>
<label style={label}>{this.state.inputText}</label>
</div>
);
}
}
export default CustomInputTextstyling;

set styling to div which contain TextInput field

I'm new to react and material ui. I'm using material ui version "1.0.0-beta.17" and react 15.6.2. Also has styled-components 2.0.0 and styled-components-breakpoint 1.0.1.
I have two TextInput fields in a div element.
const mycomponent = ({props}) => {
<div>
<SomeComponent />
<div>
<TextInput id="testId1" />
<TextInput id="testId2" />
</div>
</div>
}
Now when it render, it adds additional parent div to each input fields
Like this,
<div>
<div class="field--testId1">
<div class="FormItem__ElementWrapper-s14tem39-3 bgVlIQ">
<input id="testId1">
</div>
</div>
<div class="field--testId2">
<div class="FormItem__ElementWrapper-s14tem39-3 bgVlIQ">
<input id="testId2">
</div>
</div>
</div>
Now how can I target to the div to apply styles with class name field--testId1, field--testId2.
Here classname are generated by default material ui,
for example
.field--testId2{
width: "48%",
float: "left"
}
.field--testId2{
width: "48%",
float: "left"
}
I'm learning react and material ui so any help is much appreciated.
in order to override an existing class, you can add a styled-component wrapper instead of the wrapping div and override the child classes:
const TextInputWrapper = styled.div`
.field--testId2 {
// your custom styling
}
`
<TextInputWrapper>
<TextInput id="testId1" />
<TextInput id="testId2" />
</TextInputWrapper>
If you want to target div which has input, than you can follow these steps
Add a class to parent div, lets say wrapper
Target the closest div using > css selector
.wrapper > div {
border: 1px solid red;
width: 48%;
float: left;
margin-left: 1%;
}
input {
width: 100%;
box-sizing: border-box;
}
<div class="wrapper">
<div class="field--testId1">
<div class="FormItem__ElementWrapper-s14tem39-3 bgVlIQ">
<input id="testId1">
</div>
</div>
<div class="field--testId2">
<div class="FormItem__ElementWrapper-s14tem39-3 bgVlIQ">
<input id="testId2">
</div>
</div>
</div>
You give class directly to your textfield component and you can add your custom styles.
<TextInput className="your-class" id="testId1" />
You should use #material-ui/styles to extend your component's styles. Take a like at this answer, it's similar to your case: https://stackoverflow.com/a/67512965/8950820. Here is and example:
You should use #material-ui/styles to extend your Text Fields styles like this:
import React from 'react';
import { makeStyles, TextField } from '#material-ui/core';
const useStyles = makeStyles({
textField: {
border: 0,
borderRadius: 3,
padding: '0px 30px',
// Other styles here...
},
});
export default function MyComponent() {
const classes = useStyles();
return (
<div>
<TextField
size="large"
variant="outlined"
label="A text field title"
className={classes.textField}
/>
</div>
);
}
Learn more about the documentation at this link: #material-ui.com/styles

How to bypass React's error handling of colors

Trying to figure out if there is away of bypassing React's error handling for colors.
The first inner DIV serves as a default with an empty background if a user inputs a color that is incorrect, whether a Hex color or a string.
The second inner DIV sits on top of the first, and is meant to display the color of this.props.value.
This works fine to show my emptyBackground value in the first div, and when a correct color is inputed by the user, say orange, the second div will display a background color of orange, overlapping the first.
Now if I were to change orange to orangered, this div will change to orangered.
The part I am trying to get around is when I type orangere, it will still show the original orange color instead of the default background of the second div. It seems that react will not prompt a re-render when an improper color has been entered. Any way to get around this?
export default class ColorRender extends Component {
constructor(props) {
super(props);
this.onChange = this.onChange.bind(this);
}
onChange(e) {
this.props.onChange(e.target.value);
}
render() {
const disabled = this.props.disabled || this.props.readonly;
return (
<div
style={{ position: 'relative' }}
>
<input
type="text"
value={this.props.value}
placeholder={this.props.placeholder}
onChange={this.onChange}
style={{
marginBottom: 20,
width: `calc(100% - ${COLOR_BOX_WIDTH}px - ${COLOR_BOX_MARGIN_RIGHT}px - ${COLOR_BOX_MARGIN_LEFT}px)`,
}}
disabled={disabled}
/>
<div
style={{
...contentStyle,
backgroundImage: `url(${emptyBackground})`,
}}
/>
<div
className="color-display"
style={{
...contentStyle,
backgroundColor: this.props.value,
zIndex: 1000,
}}
/>
</div>
);
}
}
This behavior has nothing to do with React. Modern browsers will simply ignore attempts to set color properties to an unsupported value. You can easily try this yourself by opening up the dev console, selecting a DOM element somehow, and setting its color to orange with something like myElement.style.backgroundColor = 'orange'. Then try setting it to an invalid value like 'orangere'. The element will remain orange instead of reverting to an default or inherited value.
Probably the best way to address this would be to manually check that the user input is a valid color. Something like the is-color package will check not only if it's a valid color name, but HEX and RGB values as well. If the user input is valid, have React render it as usual. But if it's invalid, you can catch that and use a default or inherited value instead.
Although, this is a standard DOM element behavior (as noted by #jered), you can override it with react.
Wrap the .color-display div with another div (the .color-display-wrapper), and set the default color on it. Update the .color-display background via a CSS variable. If the value in the variable is invalid, the background color would be transparent, and the wrapper's background would be displayed.
class ColorRender extends React.Component {
state = { color: 'orange' };
onChange = (e) => this.setState({ color: e.target.value });
render() {
const {color} = this.state;
return (
<div>
<input type="text" onChange={this.onChange} />
<div className="color-display-wrapper">
<div
className="color-display"
style={{ '--color': color }}
/>
</div>
</div>
);
}
}
ReactDOM.render(
<ColorRender />,
demo
);
:root {
--color: transparent;
}
.color-display-wrapper {
width: 200px;
height: 200px;
background: url(https://picsum.photos/200/200);
}
.color-display {
position: relative;
background: var(--color);
height: 100%;
}
<script crossorigin src="https://unpkg.com/react#16/umd/react.development.js"></script>
<script crossorigin src="https://unpkg.com/react-dom#16/umd/react-dom.development.js"></script>
<div id="demo"></div>

Categories