1

I am trying to create a floating label where the label will go up when you click the input. But I am running into a problem where I am unable to call the class(the element) without affecting the other one. For example, I have 2 classes with the same class name, when I try to click on one of the other ones would work at the same time. I am trying to add an array, but as I have just started to learn JavaScript I do not know how to do it properly.

const floatinput = document.getElementsByClassName('entry-form-input');
const floatlabel = document.getElementsByClassName("tryingtoanimatelabel");

function forgetmove() {
  floatlabel[0].classList.add("myanimatelabel");
}

function removemove() {
  if (floatinput[0].value === "") {
    floatlabel[0].classList.remove("myanimatelabel");
  } else {
    floatlabel[0].classList.add("myanimatelabel");
  }
}
<div className="tryingtoanimate-container" onClick={forgetmove} onBlur={removemove}>
  <input type="text" className="entry-form-input forgetinput" name="TeamName"/>
  <label className="tryingtoanimatelabel">Team Name</label>
</div>

<div className="tryingtoanimate-container" onClick={forgetmove} onBlur={removemove}>
  <input type="text" className="entry-form-input forgetinput" name="TeamName" onChange={this.handelChange}/>
  <label className="tryingtoanimatelabel">Team Name</label>
</div>
1
  • Just a note that this can be done in CSS only using the :focus pseudo class. Commented May 18, 2020 at 20:23

2 Answers 2

1

you can try to pass an "event" as argument to the functions above. In this case your event (click or blur, etc.) will be bind to the element on which event happened, and you can refer to element as event.target

function forgetmove(event){
    event.target.classList.add("myanimatelabel");
}

function removemove(event){
    if (event.target.previousSibling.value === "") { //take the previous node of the element on which event happened (event.target)
        event.target.classList.remove("myanimatelabel");
    } else {
        event.target.classList.add("myanimatelabel");
    }
}


Few edits to answer...

I suggest you to use "onBlur" event on "input, also you can use event.CurrentTarget, if you want to take exact element on which event happened excluding their child elements.
The final code will looks like this:

class App extends React.Component {
    constructor(props) {
        super(props);
        this.state = {value: ''};

        this.handleClick = this.handleClick.bind(this);
        this.handleBlur = this.handleBlur.bind(this);
    }

    handleClick(event) { // using "currentTarget" to take element on which event happened, this will ignore cases where we would click on child elements
        let _label = event.currentTarget.querySelector('label');
        let _input = event.currentTarget.querySelector('input');
        _label.classList.add('myanimatelabel');
        _input.focus();
    }

    handleBlur(event) {
        let _input = event.target; // using "target" to take element on which event happened
        let _label = _input.nextElementSibling; // taking next element to input

        if (_input.value === "") {
            _label.classList.remove('myanimatelabel');
        } else {
            _label.classList.add('myanimatelabel');
        }
    }

    render() {
        return (
            <div className="wrapper">
                <div onClick={this.handleClick}>
                    <input type="text"  onBlur={this.handleBlur} />
                    <label className="tryingtoanimatelabel">
                        Team Name
                    </label>
                </div>
                <div  onClick={this.handleClick} >
                    <input type="text"  onBlur={this.handleBlur}/>
                    <label className="tryingtoanimatelabel">Team Name</label>
                </div>
            </div>
        );
    }
}

ReactDOM.render(<App />, document.getElementById('root'));
.wrapper > div {
    position: relative;
    margin-top: 30px;
    margin-left: 30px;
    display: inline-block;
}
.wrapper input {
    padding-left: 10px;
    padding-top:3px;
}

.wrapper label {
    position:absolute;
    left: 10px;
    top: 3px;
    transition-duration: 0.6s;
    cursor: text;
}

.wrapper .myanimatelabel {
    top: -25px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="root"></div>

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

3 Comments

it gives me a "TypeError: Cannot read property 'value' of null"
@Hypnoeye ohh, sorry about that. Just fixed it I’ve noticed that you used onBlur event on parent element. Don’t fully understand the reason behind that, so I suggest you to use onBlur event on input instead. Also with onClick u can use «event.currentTarget», so the child elements will be not selected with event. I’ve attached to answer the working example, hope it will help you
Thank you so much.
0

Add a numeric value at the end of the class name so it's unique or give each id="id1" and target that ID specifically that way

Comments

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.