Martin
Martin

Reputation: 3058

onBlur event on composed component (input + Button)

I am trying to make a "composed component" which consists of an input field and a button.

I have the following jsfiddle as example:

http://jsfiddle.net/stt0waj0/

<div id="myComponent">
    <input type="text" onBlur="this.style.border='1px solid red';">
    <button type="button" onClick="alert('Hello World');">ClickMe</button>
</div>

The behavior I want is that when I leave the input field without writing any content, I get a validation error (red border in this case). This already works in the fiddle (content validation is not the scope of the question).

However, when I leave the input field by pressing the button, I will open a dialog which allows to select values for the input field, so in that case, I don't want the validation to run.

So, the concrete question about the fiddle: Can I click the input field, and then click the button and not have a red border? But, if I click the input field, and then click somewhere else, I want the red border (any onBlur except when button was clicked).

Is this possible without dirty tricks?

Things I want to avoid:

Just to make it clear on what I'm looking for and why this question is interesting: the onBlur event is fired before the onClick event. However, I normally would need the onBlur to know that the onClick comes next, which is not possible. That's the point of the question.

Imagine a date picker which validates on empty field, when the field has focus and you press the calendar, you will get a validation error even though you're selecting a date. I want to know if there is an elegant way to handle such cases.

Upvotes: 1

Views: 1305

Answers (1)

Rainer Plumer
Rainer Plumer

Reputation: 3753

To make this work, you can postpone your validation function if user pressed the button.

Below is sample code and fiddle to show what i mean. * Updated the fiddle to use select dropdown instead of a button * Fiddle Demo

input.error {color: red; border: 1px solid red;}

<div id="myComponent">
<input id="btn" type="text" onBlur="inputBlur()">
<select type="button" data-btn="btn" onclick="inputButtonClick()" onchange="selectChange()" onblur="selectBlur()">
    <option value="">choose</option>
    <option value="item1">item1</option>
    <option value="item2">item2</option>
    <option value="item3">item3</option>
</select>
</div>

window.validate = function(input) {
    //do your validation
    var val;
    console.log("Validating");
    val = input.val();

    if ( !val || !val.length) {
        input.addClass("error");
        console.log("Something is invalid");
    } else {
        //all good
        console.log("All valid");
    }
    //clear error after x time to retry
    setTimeout(function() {
        $(".error").removeClass("error");
        $("input").removeAttr("data-btn-active") ;
    }, 3000);
}
window.selectBlur = function() {
    var input = $("#" + $(event.target).attr("data-btn"));
    validate(input);
}
window.selectChange = function() {
    var input = $("#" + $(event.target).attr("data-btn"));
    console.log("change", $(event.target).val() );
    input.val( $(event.target).val() );
    validate(input);
}
window.inputButtonClick = function() {
    var input = $("#" + $(event.target).attr("data-btn"));
    input.attr("data-btn-active", "true");
     console.log("inputButtonClick",input );
}
window.inputBlur = function() {
    var input = $(event.target);
    //give a bit of time for user to click on the button
    setTimeout(function() {
        if (!input.attr("data-btn-active" ) ) {validate(input);}
    }, 100);
}
$(document).ready(function() {

});

Upvotes: 1

Related Questions