jimscafe
jimscafe

Reputation: 1091

On-page data entry interaction with Vue.js

I have a data input page where various actions are required when certain data is input. Currently to manipulate the data I send the data changes back to the server and refresh the screen. The application is used on an internal network for production management purposes - so no issue with reloading time or file sizes for js libraries etc. I thought I would experiment with using javascript to do all this without reloading and this led to considering angular, react and other similar frameworks/libraries. Firstly, nearly all the demonstration introductions show data being entered in one element and immediately updated in another. This is not particularly useful here as only complete data is updated (where is such a process useful!). I looked at checking keystrokes and then accepting the data on the enter key or leaving focus of the element and having the escape key return the data to its initial state. If the data was accepted then various different processes need to be initiated. One framework that seemed 'easy' to learn and which might help was Vue.js. In the example below I have created a component for a data entry block (label and entry element) with the idea of passing parameters and updating when appropriate - but I am stuck how to implement this. My Vue instance is attached to a div, and my component is a global component. Inside the div I have

        <ms-pages></ms-pages>

And my component is:

  Vue.component('ms-pages', {
template: '<div class="form-group row">' +
            '<label class="col-xs-4 col-form-label">Pages</label>' +
            '<div class="col-xs-8">' +
              '<input v-model="mspages" class="form-control" type="text">' +
            '</div>' + 
           '</div>',
 })

The v-model throws an error, though I defined mspages in the Vue instance, I also tried to define it in the component. Then I tried to define the component in the Vue instance, but couldn't find how to do this. One thought is the component could save the current state of the data being entered, but this seems pointless as that data is in the enter element. Leading me to think perhaps this approach is wrong.

My javascript knowledge is not great but I could try to write my own functions listening to keystrokes on various elements, but then the code would probably become long and complex. (I find it much easier to do this stuff in python..)

Any help is much appreciated.

Upvotes: 0

Views: 629

Answers (1)

craig_h
craig_h

Reputation: 32704

Vue is MVVM, so the view data needs to reflect the model data, but that doesn't mean you need to fire your updates every time the data updates, Vue will just keep everything synchronised for you. The usual way to approach this is to have a parent pass a prop to a component and then have the component $emit the update when some event happens. Here's an example of how you might have a component that updates your values when the enter key is pressed:

Bus

var bus= new Vue(); // A Vue instance to emit events onto

Component Template:

<template id="my-input">
  <div>
    <input v-model="inputVal" v-on:keyup.enter="updateVal"/>
  </div>
</template>

Component:

Vue.component('my-input', {
  template: '#my-input',
  data(){
    return {
      inputVal: ""
    }
  },
  props: ['initVal'],
  created(){
    this.inputVal = this.initVal
  },
  methods: {
    updateVal(){
      bus.$emit('updateVal', this.inputVal);
    }
  }
});

Main Markup:

<div id="app">
  <my-input :init-val="myInput"></my-input>
  {{myInput}}
</div>

Parent Vue Instance:

new Vue({
  el: '#app',
  data: {
    myInput: "foo"
  },
  created(){
    bus.$on('updateVal', (updatedVal) =>{
      this.myInput = updatedVal;
    });
  }
});

I realise that you are new to Vue so I'll break down what is happening:

First we have a bus (just an empty Vue instance) that we $emit events onto and listen for them, notice this line: bus.$emit('updateVal', this.inputVal);

Here we are emitting an event called 'updateVal' on the the bus when the enter key is pressed and listening for it in our parent, with this:

bus.$on('updateVal', (updatedVal) =>{
  this.myInput = updatedVal;
});

If you take a look at the component template you can see that we have used v-on:keyup.enter="updateVal" which calls the updateVal method when the enter key is pressed, which emits the event.

You should also notice that v-model is only keeping the component input synchronised, when we want to make an actual update we fire an event and update our main variable.

The only other thing here is that we have passed a prop to the component to set an initial value.

Here's the JSFiddle: https://jsfiddle.net/k7cvq0f0/

Upvotes: 1

Related Questions