Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Focus input of freshly added item

Tags:

vue.js

So I have a list of items and list of inputs linked to each item via v-for and v-model.

I click a button and add new item to that list. I want to focus input which is linked to newly added item.

Can't figure out how to achieve this goal.

<div id="app">
  <div v-for="item in sortedItems">
    <input v-model="item">
  </div>
  <button @click="addItem">
    add
  </button>
</div>


new Vue({
  el: '#app',
  data: {
    items: []
  },
  methods: {
    addItem: function() {
      this.items.push(Math.random());
    }
  },
  computed: {
    sortedItems: function() {
      return this.items.sort(function(i1, i2) {
        return i1 - i2;
      })
    }
  }
})

Here's fiddle with sorted list https://jsfiddle.net/sfL91r95/1/

Thanks

like image 486
kerby Avatar asked Oct 30 '25 21:10

kerby


2 Answers

Update: inspired by pkawiak's comment, a directive-based solution. I found that calling focus in the bind section didn't work; I had to use nextTick to delay it.

Vue.directive('focus-on-create', {
  // Note: using Vue 1. In Vue 2, el would be a parameter
  bind: function() {
    Vue.nextTick(() => {
      this.el.focus();
    })
  }
})

new Vue({
  el: '#app',
  data: {
    items: []
  },
  methods: {
    addItem: function() {
      this.items.push(Math.random());
    }
  },
  computed: {
    sortedItems: function() {
      return this.items.sort(function(i1, i2) {
        return i1 - i2;
      })
    }
  }
})
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<div id="app">
  <div v-for="item in sortedItems">
    <input v-focus-on-create v-model="item">
  </div>
  <button @click="addItem">
    add
  </button>
</div>

Original answer: Make your input a component so that you can give it a ready hook.

const autofocus = Vue.extend({
  template: '<input v-model="item" />',
  props: ['item'],
  ready: function() {
    this.$el.focus();
  }
})

new Vue({
  el: '#app',
  data: {
    items: []
  },
  methods: {
    addItem: function() {
      this.items.push(Math.random());
    }
  },
  components: {
    autofocus
  },
  computed: {
    sortedItems: function() {
      return this.items.sort(function(i1, i2) {
        return i1 - i2;
      })
    }
  }
})
<script src="//cdnjs.cloudflare.com/ajax/libs/vue/1.0.26/vue.min.js"></script>
<div id="app">
  <div v-for="item in sortedItems">
    <autofocus :item="item"></autofocus>
  </div>
  <button @click="addItem">
    add
  </button>
</div>
like image 97
Roy J Avatar answered Nov 02 '25 14:11

Roy J


I Like to extend @Roy's answer. if you are using any UI framework then it will create DIV and within the DIV input tag will be created so this Snippet will handle that case.

Vue.directive('focus-on-create', { 
    bind: function(el) { 
          Vue.nextTick(() => { 
              el.querySelector('input').focus()
          })
    }
})
like image 20
Ronak Bokaria Avatar answered Nov 02 '25 14:11

Ronak Bokaria