M.Koops
M.Koops

Reputation: 155

How can I configure Simple-keyboard in vue3 with custom layout and clearInput()

New to Vue I am trying to make a simple game. In my vue3 component in the template I use the component. And it works:)

                <input
                    :value="input"
                    class="input"
                    @input="onInputChange"
                    placeholder="Tap on the virtual keyboard to start"
                >
                <SimpleKeyboard 
                    ref="simplekeyboard"
                    @onChange="onChange" 
                    @onKeyPress="onKeyPress" 
                    :input="input"
                    :layout="layout"
                ></SimpleKeyboard>

Now I want to acces the clearInput() function, and set a custom Layout according to documentation.

The layout is defined in the gamecomponent. Also I have a method in the game-component checking if a player has entered the right description. It wordks like a charm but the input variable in the Simple-Keyboard is not cleared

_match(){
            if(this.showCard.description.toUpperCase() === this.input.toUpperCase()){    
 
                 this.matches++;
                 this.input='';
                 this.simpleKeyboard.clearInput();
                
            }

Gives an error:

    Uncaught TypeError: Cannot read properties of undefined (reading 'clearInput')

I do not know how to get in contact with the simple-keyboard component. I tried:

     mounted() {
        this.simpleKeyboard = this.$refs.simplekeyboard;
    },

    data() {
        return{
            simpleKeyboard:{},
    }

When I check the simple-keyboard component in the Vue-devtools I read:

keyboard:Unknown Component

Strange I think, since the keyboard works fine, albeit in the default settings. But apparently there is something I do not understand yet. Can anyone point me to a solution on how to get to the settings of the simple-keyboard component instead of only being able to read the output?

The SimpleKeyboard component itself looks like:

<template>
  <div class="simple-keyboard"></div>
</template>

<script>
import Keyboard from "simple-keyboard";
import "simple-keyboard/build/css/index.css";

export default {
  name: "SimpleKeyboard",
 
  data: () => ({
    keyboard: null
  }),
  mounted() {

    console.log("Before new Keyboard()");

    this.keyboard = new Keyboard({
      onChange: this.onChange,
      onKeyPress: this.onKeyPress
    });

    console.log("After new Keyboard()");
  },
  methods: {
    onChange(input) {
      this.$emit("onChange", input);
    },
    onKeyPress(button) {
      this.$emit("onKeyPress", button);

      /**
       * If you want to handle the shift and caps lock buttons
       */
      if (button === "{shift}" || button === "{lock}") this.handleShift();
    },
    handleShift() {
      let currentLayout = this.keyboard.options.layoutName;
      let shiftToggle = currentLayout === "default" ? "shift" : "default";

      this.keyboard.setOptions({
        layoutName: shiftToggle
      });
    }

Upvotes: 0

Views: 1305

Answers (3)

Kalnode
Kalnode

Reputation: 11384

Pass a class into the keyboard instance

Ideally you'd pass a class name, for your keyboard container, into the keyboard instance, as seen in many demos, including the official simple-keyboard Vue demo:

https://codesandbox.io/p/sandbox/github/hodgef/vue-simple-keyboard/tree/master/?file=%2Fsrc%2FSimpleKeyboard.vue

When you instantiate new Keyboard, in the first parameter you'd ideally pass the class of whatever is your containment (div) in the template.

If you have a reason to diverge from this way, so be it, but this is how many simple-keyboard examples do it. Ultimately going the ref way, you're just coming full-circle. What's the benefit of the extra complexity?

Inside your keyboard component

// Wherever you instantiate, like 'mounted'
this.keyboard = new Keyboard('myKeyboardContainer', {
  onChange: this.onChange,
  onKeyPress: this.onKeyPress
  // ... many other options
})

// ...

<template>

    <!-- simple-keyboard will render inside of this wrapper -->
    <div class="myKeyboardContainer"></div>

</template>

Upvotes: 0

M.Koops
M.Koops

Reputation: 155

Solved it, quite silly mistake from a noob actually.

All I had to do was add a reference:

 <SimpleKeyboard 
                    ref="simplekeyboard"
                    @onChange="onChange" 
                    @onKeyPress="onKeyPress" 
                    :input="input"
                    :layout="layout"
                ></SimpleKeyboard>

AND define the method in the child as well. I thought I could immediately access the methods of Simple-Keyboard, but actually I had to acces the method in the simple-keyboard claas withing the component. So after adding:

 clearInput(){
      this.keyboard.clearInput();
    },

in the Simple-Keyboard component, I could access the method,

Feels something like .keyboard.clearInput(), acceess in a two step approach

Upvotes: 1

Mr. Innovator
Mr. Innovator

Reputation: 95

You did not add the add the component to your data, that's why you cannot access it.

You can use Vue.component()

var keyboard = Vue.component('keyboard');

Upvotes: 0

Related Questions