Home > Software design >  Why is the jquery object not returning its value?
Why is the jquery object not returning its value?

Time:04-13

I've been trying to figure this problem out for the last 2 days and have not found any solution so far.

Im trying to attach a .click() listener to all elements of a list, but any time I use this or $(this) none of the jquery functions work, for example using .val() returns undefined even though it has a value.

I'm using fomantic-ui but I've also tried the same code without and it doesn't work either. I'm also using NodeJS and Express, in case that makes a difference.

Further testing showed me that for some reason this doesn't work:

$('#first_name').on('input', () => {
    const name = $(this)
    const field = name.parent()

    if (!name.val().match(/^\p{L}{1,16}$/u)) {
        field.attr('class', 'field error')
        name.prop('valid', false)
    } else {
        field.attr('class', 'field success')
        name.prop('valid', true)
    }
})

But if I change it to this, everything is fine:

$('#first_name').on('input', () => {
    const name = $('#first_name') //Only Change...
    const field = name.parent()

    if (!name.val().match(/^\p{L}{1,16}$/u)) {
        field.attr('class', 'field error')
        name.prop('valid', false)
    } else {
        field.attr('class', 'field success')
        name.prop('valid', true)
    }
})

And also this both return false

console.log($(this) === $('#first_name'), $(this) == $('#first_name'))
//false false

I have tried all sorts of combinations but nothing I can think of works, and nothing I found anywhere online has either. Maybe I just don't understand how this is supposed to work but I've tried reading the jquery documentation but it didn't help me.

Can anyone help me?

CodePudding user response:

You're using an arrow function, so the value of this will be inherited from the parent context. A console.log should show you what that is.

You probably want to use a regular anonymous function, assuming jQuery calls the function with the HTML element set to the context of this.

$('#first_name').on('input', function() {
   // ...
});

https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Functions/Arrow_functions

Arrow functions don't have their own bindings to this or super, and should not be used as methods.

CodePudding user response:

Here I have an example where I use a class instead of an id on the input group.

  • Your scope issue is resolved by using function(event){ form for the function
  • I use the .closest('.wrapper') to get the "owner" of the group.
  • I hooked the event handler using the container ID: $('#inputs-container')
  • I use a data attribute and set a value for that to do some "creative" css depending upon the condition
  • IF for some reason you need to get the container, you can use the event.delegateTarget - this is the container element with the id id="inputs-container"
  • I added the change event also in case someone does a "paste" or you change the value programmatically
  • I would suggest you use semi-colons on the ends of the lines in the script; at some point not doing so will cause a very hard to find bug

I admit this is a bit of overkill but perhaps someone can get some use of the example even though it is admittedly a bit "verbose". Try it out by entering in text, numbers and spaces in each of the three inputs.

$('#inputs-container').on('input change', '.first-name',function(event) {
  const $input = $(this);
  const field = $input.closest('.wrapper');
  //console.log(field.data('goodness'), field.get(0).dataset);
  let val = $input.val();
  const regex = /^\p{L}{1,16}$/u;
  const isGood = val.match(regex) == val;
  //console.log('Good:', val, isGood);
  field.get(0).dataset.goodness = isGood ? "success" : "error";
  $input.prop('valid', isGood);
});
.wrapper {
  border: 1px solid #d0d0d0;
  border-width: 0.5em;
  padding: 0.5em;
}

.wrapper[data-goodness="error"] {
  border-color: #FF0000;
  border-width: 0.5em;
}

.wrapper[data-goodness="error"] .err-message:before {
  content: "Do Better";
  padding-left: 1em;
}

.wrapper[data-goodness="success"] {
  border-color: #00FFdd;
}

.wrapper[data-goodness="success"] .err-message:before {
  content: "Doing well so far!";
  padding-left: 1em;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="inputs-container">
  <div  data-goodness="cheers">
    <div >
      <div >We are happy to have:</div>
      <label>First Name</label>
      <input type="text"  /><span ></span>
    </div>
  </div>
  <div  data-goodness="cheers">
    <div >
      <div >We are happy to have:</div>
      <label>First Name</label>
      <input type="text"  /><span ></span>
    </div>
  </div>
</div>
<div  data-goodness="cheers">
  <div >
    <div >OUT OF SCOPE</div>
    <label>First Name</label>
    <input type="text"  /><span ></span>
  </div>
</div>

CodePudding user response:

Try this

$('#first_name').on('input', (e) => {
    let el = e.target;
    const name = $(el).val();
    const field = name.parent()

    if (!name.val().match(/^\p{L}{1,16}$/u)) {
        field.attr('class', 'field error')
        name.prop('valid', false)
    } else {
        field.attr('class', 'field success')
        name.prop('valid', true)
    }
})
  • Related