-1

I have a user input with id userName and I am trying to get the user input text using $("#userName").val() after user has finished inputting the text in the textbox and then storing it in a variable (a directory path), however, I'm getting undefined for $("#userName").val(). I'm thinking that the undefined is occurring cause the text field is not ready at runtime, so I'm trying to set up a callback function to use in my directory path but i'm still getting undefined when I do console.log("This is the field name: " + getUserName()); Below is my callback function:

function getUserName(){
    $("#userName").keyup(function(){
        console.log(this.value);
        return this.value;
    });
}

I am trying to use this in my directory variable here (the variable filePath is outside the function getUserName()):

var filePath = "/my/path/to/the/file/" + getUserName() + ".txt";

However, when I do this I am still getting undefined. Am I doing something wrong here?

Update:

name.html:
<div class="subArea" id="pvDiv">
    <p id="nameP">Name:
        <input id="userName" class="userInput" type="text" placeholder="Enter Name">
    </p>
</div>
tiger_groove
  • 956
  • 2
  • 17
  • 46
  • provide the html of your input – ztadic91 Feb 09 '18 at 23:26
  • What you have provided is not a "callback" function. You have a function that registers an event handler on an element when that function is called (and yes, it will get re-bound for every time the function is called). – mhodges Feb 09 '18 at 23:28
  • 2
    The `getUserName()` function doesn't actually return anything. It attaches an event handler for the `keyup` event to the element with the id `userName` and then exits, returning `undefined` by default. The function that handles the `keyup` event return `this.value` to, well, the event handling routine. If you wanted to get the user name in the `getUserName()` function, `return $('#userName').val();` would work better. – Heretic Monkey Feb 09 '18 at 23:29
  • On a secondary note - you cannot return values from event handlers, so `return this.value` is meaningless in this context – mhodges Feb 09 '18 at 23:29
  • 1
    Your two easiest options are to have `getUserName()` return `$("#userName").val()` or if you want to update the file path on each keystroke, simply put `filePath = "my/path/" + this.value + ".txt"` inside your `keyup` handler. Make sure you define `filePath` outside of the event handler so that it updates and is visible wherever you need it. – mhodges Feb 09 '18 at 23:32
  • @ztadic91 Done. – tiger_groove Feb 09 '18 at 23:33

4 Answers4

2

Your code doesn't make sense for a lot of reasons, most of which can be found in the comments under your question. In short:

  • you're setting the keyup event listener inside the function, so unless the function is called the keyup event handler won't work, because the event listener won't have been set.

  • you overlook the fact that the execution of an event handler is an asynchronous operation and doesn't return anything.

  • even if the above were possible, you still don't have a return statement in getUserName.

Try using one of the following events and construct the path inside the event handler:

  • the blur event, which fires when the input loses focus.
  • the change event, which fires when a change in the value of the input occurs.

Code:

$("#userName").on("change", function() {
   var filePath = "/my/path/to/the/file/" + this.value + ".txt";
   console.log("The new path is '" + filepath + "'.");
});
Angel Politis
  • 10,955
  • 14
  • 48
  • 66
  • 1
    `.on("change")` would be more appropriate, so this does not get triggered each time the user focuses and blurs the field (via tab or clicks) – mhodges Feb 09 '18 at 23:35
  • I'd leave that to the OP to decide @mhodges. But thanks for the comment; I made sure to include your suggestion in the answer. – Angel Politis Feb 09 '18 at 23:47
  • The event handler callback is not an asynchronous operation, it just run in its own scope. All event handlers are fired synchronously and in order of binding – ecarrizo Feb 10 '18 at 00:08
  • 1
    I didn't say the *callback* is an asynchronous operation @ecarrizo. I said its *execution* is, since the callback isn't executed immediately when passed as an argument, but after the event has fired. – Angel Politis Feb 10 '18 at 00:11
  • I misslead, since there's a difference of time between the user pressing the button and the code creating the handler, the code execution is asynchronously between them (do not coincide in time). I Missread and tought you were meaning something else. – ecarrizo Feb 10 '18 at 00:20
1

The problem with getting the value of the input using the $("#userName").val() directly probably is due that the DOM Is not ready yet when you execute that code or you are not waiting to certain event to happen, Take a look at

call a function after complete page load

and the Keyup Event handler on the input is not properly implemented since it will return nothing in your function.

Then depending on how you want to handle the user input is the solution that you need to implement, Something like this should work.

var filePath;

function updateFilePath() {
    filePath = 'myPath/' + this.value + '.txt';
    console.log('The file path has changed to: %s', filePath);
}

// When the dom Is ready to be used, you execute your code.
$(function() {
    // Add an event handler when userName input value change 
    $('#userName').on('change', updateFilePath);
})

As said in comments you can use other events like 'keyup', 'blur' or whatever fit your needs better, but probably 'change' is the best option for your intention.

ecarrizo
  • 2,758
  • 17
  • 29
1
  • You can bind a custom event, i.e: refreshAutoComplete to your target element.
  • Trigger that event when the user enters information into your input text.
  • Pass the entered data throughout the trigger executions
$('#autocompleteResult').trigger('refreshAutoComplete', [{userData: this.value}]);
  • Get that data and execute your logic
var filePath = "/my/path/to/the/file/" + data.userData + ".txt";
$(this).html(filePath);

This approach separates the responsibilities:

  1. User input event.
  2. Manipulation of the entered user data.

Now your logic for filePath is separated and can be re-used from other parts of your JS application.

$(document).on('input', '#userName', function() {
  $('#autocompleteResult').trigger('refreshAutoComplete', [{userData: this.value}]);
});

$(document).on('refreshAutoComplete', '#autocompleteResult', function(e, data) {
  var filePath = "/my/path/to/the/file/" + data.userData + ".txt";
  $(this).html(filePath);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="subArea" id="pvDiv">
  <p id="nameP">Name:
    <input id="userName" class="userInput" type="text" placeholder="Enter Name">
  </p>
  <p id='autocompleteResult'>
  </p>
</div>
Ele
  • 33,468
  • 7
  • 37
  • 75
0

The function you created is just binding the keyup event to the text box. That function getUsername gets invoked when you are typing in it.

To get its value you could use, $("#userName").val() So you can set filepath using

var filePath = "/my/path/to/the/file/" +  $("#userName").val() + ".txt";

If you need to do it only when the userName field exists, you can do the following:

if( $("#userName").length > 0)
    filePath = "/my/path/to/the/file/" +  $("#userName").val() + ".txt";

Hope this helps.

Sheikh Azad
  • 353
  • 2
  • 11
  • 1
    It would be better if you do not fetch the element twice on the example with the validation. store it in a variable and use it as the element reference. – ecarrizo Feb 09 '18 at 23:56
  • I agree. Will make sure I provide optimized example code in the future. – Sheikh Azad Feb 10 '18 at 05:47