How To Listen For An [enter] On An Element UI Form?

I’m trying to switch over to Element UI on some of my forms, but running into several problems.

On my old from I’m using I’m using @keyup= to listen for any and all keystrokes, including [enter].

As near as I can tell ElementUI el-input only allows to listen for a change. But if [enter] is pressed, the input value hasn’t changed.

Is there some workaround? How else might I listen for an [enter] on a form inputs?

1 Like

Hey @Emily

I had a similar issue recently. All you have to do is add the ‘native’ modifier to the keyup event. For example:

<el-form ...>
    ...
        <el-input @keyup.enter.native="onSubmit" ...></el-input>
<el-form>

I’m not sure if you have to do this on every input on the form, or if it would also be possible to do a @submit.native="..." on the form itself, which should be triggered by pressing enter on on any focused input in the form.

8 Likes

Using @keyup.native=… I can get the a keyup listener to work. For some reason, I can’t get @keyup.enter.native= to work.

For some reason, an enter causes the whole DOM to reload & the method is never called? (I should note, it does not do this when not using Element UI???)

Here’s the code for the template:

<template>
  <div class="row">

    <el-form :inline="true" class="form-inline">
      <el-form-item>
        <el-input type="number" min=0 placeholder="Enter price point" v-model="pricePoint" @keyup.enter.native="checkEnter">
        </el-input>
      </el-form-item>

      <el-form-item>
        <el-button type="primary" icon="plus" :disabled=disabledToggle @click.prevent="createNew">
          Add Price Point
        </el-button>
      </el-form-item>

    </el-form>
  </div>
</template>

Here’s the method:

  checkEnter (object) {
    console.log('CHECKING ENTER')
    console.log(object)
  }

(Here’s the component in full context)

<template>
  <div class="row">

    <el-form :inline="true" class="form-inline">
      <el-form-item>
        <el-input type="number" min=0 placeholder="Enter price point" v-model="pricePoint" @keyup.enter.native="checkEnter">
        </el-input>
      </el-form-item>

      <el-form-item>
        <el-button type="primary" icon="plus" :disabled=disabledToggle @click.prevent="createNew">
          Add Price Point
        </el-button>
      </el-form-item>

    </el-form>
  </div>
</template>

<script>

  export default {
    data: function () {
      return {
        pricePoint: '',
        disabledToggle: true
      }
    },
    methods: {
      // Checks to see that price is > 0 & not already in existing prices.
      checkPrice () {
        if (this.pricePoint > 0 && this.$store.state.pricePoints.includes(this.formatNumber(this.pricePoint)) === false) {
          return true
        }
        return false
      },
      // Removes leading zeros, except for 1 in case of a number less then 1.
      formatNumber (number) {
        number = number.replace(/^0+/, '')
        if (number < 1) {
          number = '0' + number
        }
        return number
      },
      // Checks the price input & enables the add price button if checks pass.
      checkPriceInput (object) {
        if (this.checkPrice() === true) {
          this.disabledToggle = false
          return
        }
        this.disabledToggle = true
        return
      },
      // Sends the new price point to parent if checks passed.
      createNew () {
        console.log('CREATE NEW')
        if (this.checkPrice() === true) {
          // this.$store.commit('ADD_PRICE_POINT', this.pricePoint)
          this.pricePoint = ''
          return
        }
        console.log('DIDNT PASS')
        object.preventDefault()
        return
      },
      checkEnter (object) {
        console.log('CHECKING ENTER')
        console.log(object)
      }
    }
  }
</script>
<style>

</style>

Can you see anything that would make the DOM reload?

OK, after doing a lot to isolate the bug, it seems to come down to something to do with that it’s inside an el-form tag.

If I remove the el-button tag, an enter in the el-input tag does not cause the DOM to reload. Same applies if I remove the button tag, but keep the form tag. Near as I can tell this must have something to do with some kind of form submit call I’m not preventing from happening?

After testing the form examples on Element UI site, the ones I tested caused the DOM to reload on [enter]. Maybe I’m missing something but it looks like I can’t listen for [enter] inside a form element?

@Emily, it is the default behavior of submitting a form to reload/redirect the page to the form action. Just make sure that you preventDefault() on the event passed into your onSubmit function, e.g.

...
methods: {
  ...
  onSubmit(event) {
    event.preventDefault()
    ...
  }
}

EDIT: I apologize for referring back to my original example instead of the code that you posted for this explanation.

For more context… it’s not the form tag, its the button code. If this code is in the form, then it causes a reload on enter. If it’s not, it doesn’t??

 <el-button type="primary" icon="plus"
      :disabled=disabledToggle
      @click.prevent="createNew">
      Add Price Point
    </el-button>

I tried the prevent on the listener, as well as prevent default in the method.

Strange…

@click.prevent="createNew" is relying on events that are being interpreted by Vue. When we add the .native modifier, we are leaving Vue’s context; so, you have to explicitly prevent default on the form’s onsubmit function.

This is how I’m doing that on the method:

  createNew (object) {
    if (this.checkPrice() === true) {
      this.$store.commit('ADD_PRICE_POINT', this.pricePoint)
      this.pricePoint = ''
      return
    }
    object.preventDefault()
    return
  }

createNew isn’t the method that you’re calling when the user presses enter on the input. Try adding the preventDefault to your checkEnter function.

I did test that too. Here’s the code with that test added. The first form works as it should, without reloading the DOM on enter (the form without Element UI). The 2nd on (Element UI) doesn’t… no matter what I seem to try? (Grrr… all day trying to fix this one.)

<template>
  <div class="row">

    <form role="form" class="form-inline">
      <div class="form-group">
        <input type="number" min=0 placeholder="Enter price point" class="form-control" v-model="pricePoint" @keyup="checkPriceInput">
        </input>
      </div>
      <button :class=buttonClass @click.prevent="createNew">Add Price Point</button>
    </form>


    <el-form :inline="true" class="form-inline">

      <el-form-item>

        <el-input type="number" min=0 placeholder="Enter price point" v-model="pricePoint" @change="checkPriceInput" @keyup.enter.native.="checkEnter">
        </el-input>
      </el-form-item>

      <el-form-item>
        <el-button type="primary" icon="plus" :disabled=disabledToggle @click.prevent="createNew">
          Add Price Point
        </el-button>
      </el-form-item>

    </el-form>
  </div>

</template>

<script>

  export default {
    data: function () {
      return {
        pricePoint: '',
        disabledToggle: true
      }
    },
    methods: {
      // Checks to see that price is > 0 & not already in existing prices.
      checkPrice () {
        if (this.pricePoint > 0 && this.$store.state.pricePoints.includes(this.formatNumber(this.pricePoint)) === false) {
          return true
        }
        return false
      },
      // Removes leading zeros, except for 1 in case of a number less then 1.
      formatNumber (number) {
        number = number.replace(/^0+/, '')
        if (number < 1) {
          number = '0' + number
        }
        return number
      },
      // Checks the price input & enables the add price button if checks pass.
      checkPriceInput (object) {
        console.log('Checking price INPUT')
        console.log(object)
        if (this.checkPrice() === true) {
          this.disabledToggle = false
          return
        }
        this.disabledToggle = true
        object.preventDefault()
        return
      },
      // Sends the new price point to parent if checks passed.
      createNew (object) {
        object.preventDefault()
        if (this.checkPrice() === true) {
          this.$store.commit('ADD_PRICE_POINT', this.pricePoint)
          this.pricePoint = ''
          return
        }
        object.preventDefault()
        return
      },
      checkEnter(object) {
        console.log("CHECK ENTER")
        object.preventDefault()
      }
    }
  }
</script>
<style>

</style>

As near as I can tell, the method never gets called. The DOM reloads when enter is pressed. So disabling at the method I don’t think will work.

No luck with this either: @keyup.enter.native.preventDefault=“checkEnter”.

Well, without much deeper evaluation, all I can think of is trying to use the input outside of a form. You aren’t using a label or validation for the input, and you can attach the button to the input as if it was an inline form using a mixed input.

Then set your createNew method in the @keyup.enter.native of the input.

Outside of a form, the reload won’t happen.

Thanks… kinda hacky, but that solution worked. (Wish I hand’t had to spend 1/2 the day to figure this one out grrr…)

2 Likes

I’m sorry that we couldn’t find something better. I’ll be building a lot of form components over the next few weeks. If I find a better solution, I’ll let you know :slight_smile:

Did you try @keyup.13.native= ?

I’m aware that @keyup.enter.native= is an alias though you never know

Also try

checkEnter (object) {
  console.log('CHECKING ENTER')
  console.log(object)
  return false
}

You should <el-form @submit.prevent

It’s the form’s submit event that the enter key triggers, so preventing in the method handler of the click event will do nothing…

Hey Emily!

I was having the same problem and using <el-form @submit.prevent.native="checkEnter"> worked for me! It’s less hacky and I think is the way it should be done (as per LinusBorg).

Cheers!

5 Likes

For element ui specifically it seems @keyup.enter.native on the el-form does it:

1 Like

Thank you for this @rmarc

1 Like