Customize Vuetify Menu by adding a unique custom keypad component for editing text fields

I am currently developing an app using vuetify, and I am encountering some challenges with the v-menu feature.

The issue arises when I click on a text input field, it triggers the opening of a v-menu. Within this menu, there is a custom component that I have created, which is essentially a simple keypad ranging from 0 to 9. The objective is to use this keypad to modify the text input field.

My goal is to incorporate a save button within the menu that will allow users to save any changes made and close the menu. However, I am facing difficulties in implementing this functionality.

How can I make this work seamlessly with multiple text input fields? While this may sound like a complex process for simply editing a text input, it is essential as the app will be utilized on a large touch screen where using the onscreen keyboard is not ideal for changing numbers.

What approach would you recommend?

<v-menu bottom :close-on-content-click="false">
  <template v-slot:activator="{ on, attrs }">
    <v-text-field
      v-bind="attrs"
      v-on="on"
      v-model="result"
      readonly
    ></v-text-field>
  </template>
  <Calculator :data.sync="result" /> <-------- My keypad component
</v-menu>

Custom Keypad Component

    <template>
  <v-card class="widget" @contextmenu.prevent="" color="grey lighten-2" max-width="260" >
    <v-card-text>
      <v-card class="mb-2" elevation="1" min-height="64px" max-height="64px" tile flat color="lighten-grey" >
        <v-card-text>
          <v-text-field dense flat reverse v-model="value" :suffix="suffix" ></v-text-field>
        </v-card-text>
      </v-card>
      <v-row no-gutters class="pb-1">
        <v-col align="center" justify="center">
          <v-btn color="grey lighten-5" @click="click1" tile elevation="1" height="55px" >1</v-btn>
        </v-col>
        <v-col align="center" justify="center">
          <v-btn color="grey lighten-5" @click="click2" tile elevation="1" height="55px" >2</v-btn>
        </v-col>
        <v-col align="center" justify="center">
          <v-btn color="grey lighten-5" @click="click3" tile elevation="1" height="55px" >3</v-btn>
        </v-col>
      </v-row>
      <v-row no-gutters class="pb-1">
        <v-col align="center" justify="center">
          <v-btn color="grey lighten-5" @click="click0" tile elevation="1" height="55px" >0</v-btn >
        </v-col>
        <v-col align="center" justify="center">
          <v-btn color="grey lighten-5" @click="clickDecimal" tile elevation="1" height="55px" >.</v-btn >
        </v-col>
        <v-col align="center" justify="center">
          <v-btn color="grey lighten-5" @click="clickClear" tile elevation="1" height="55px" >C</v-btn >
        </v-col>
      </v-row>
      <v-row no-gutters class="pt-2">
        <v-col align="right">
          <v-btn @click="cancel" tile small>Cancel</v-btn>
          <v-btn class="ml-2 mr-0" @click="onSave" tile small>Save</v-btn>
        </v-col>
      </v-row>
    </v-card-text>
  </v-card>
</template>

<script>
export default {
  props: ['data', 'suffix'],
  data() {
    return { value: '0', };
  },
  methods: {
    click0() {
      if (this.value.toString().length > 9) return;
      if (this.value === '0') { this.value = ''; }
      this.value = this.value + '0';
    },
    click1() {
      if (this.value.toString().length > 9) return;
      if (this.value === '0') { this.value = ''; }
      this.value = this.value + '1';
    },
    click2() {
      if (this.value.toString().length > 9) return;
      if (this.value === '0') { this.value = ''; }
      this.value = this.value + '2';
    },
    click3() {
      if (this.value.toString().length > 9) return;
      if (this.value === '0') { this.value = ''; }
      this.value = this.value + '3';
    },
    clickClear() {
      this.value = '0';
    },
    clickDecimal() {
      if (this.value.includes('.')) return;
      this.value = this.value + '.';
    },
    onSave() {},
    cancel() {},
  },
};
</script>

Answer №1

Thank you for sharing your keypad component code. I have created a codesandbox showcasing the implementation: https://codesandbox.io/s/stack-70120821-5uyq4?file=/src/components/Keypad.vue

I have streamlined the use of the keypad component by removing the inner text field and cancel/save buttons, as well as optimizing the generation of the numpad. Feel free to customize it further according to your needs.

I have set up a watcher for the internal value number of the keypad. Whenever this value changes, an event named "output" is emitted to the parent component with the updated value.

 watch: {
    ...
    // Emitting an event to parent when inner value changes
    value(val) {
      this.$emit('output', val)
    }
  },

On the parent component, you can receive the new value by defining a custom event handler @output. The $event variable contains the data emitted from the child component. In this example, I simply update the value of the v-text-field in the parent component. However, you can also pass this value to a method for validation or other purposes.

    <Keypad :input="result" @output="result = $event" />

If you need to update the keypad value from the parent component, you can do so using the prop I have defined called input. To ensure proper functionality on initial page load, make sure to utilize the eager prop on the v-menu so that the custom keypad component is rendered right from the start.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Is it possible to execute appendChild in the context of JS-DOM-creation?

Hey there, I'm a newbie trying my hand at DOM creation. I've encountered a strange issue with appendChild - the first and second tries work fine, but I'm completely stuck on the third attempt. Here's my HTML: <html> <head> ...

What is the best way to pass props down to grandchildren components in React?

I'm trying to pass some props from a layout to its children. The issue is, it works fine when the child component is directly nested inside the layout, but it doesn't work when the child component is wrapped in another element like a div. Exampl ...

Deliver transcluded data to the descendant element of a hierarchical roster

I understand that there have been similar questions asked before, but my situation is slightly different. I am currently constructing a nested list and I want to include custom HTML content in each grandchild element alongside some common HTML. The problem ...

Nested loop combining Callback and Promise with two API requests

I apologize for the lackluster title, but I couldn't come up with anything more suitable. If this issue has already been addressed, please let me know in the comments and I will delete it promptly. However, keep in mind that this is a specific questio ...

Marker on Google Maps in Dark Mode is not displaying properly

I have integrated a custom map into my website using the npm module called google-map-react. The provided tutorial demonstrates how to implement a basic marker on the map, and you can find it here: . Here is an example of what it should look like: import ...

Activate a function when the v-data-table in Vuetify is expanded and then collapsed

While trying to create a v-data-table, I came across some odd behavior when monitoring the expanded.sync value. The first layer's expanded.sync value seems normal, but the second layer's expanded.sync has three consecutive identical records. I w ...

Accessing a JSON key using a JavaScript variable

Is there a way to dynamically replace the key "Argentina" in a JSON object with a javascript variable string? jQuery(document).ready(function() { $.getJSON('countries.json', function(data) { var output= data.Argentina[0].countryPho ...

Animating elements within a D3.js force layout

I am looking to create a unique data visualization that resembles floating bubbles with text inside each bubble. Currently, I have a prototype using mock data available here: JSfiddle // Here lies the code snippet // ... However, my current challenge li ...

Creating nested directories in Node.js

I am attempting to accomplish the following task Create a function (in any programming language) that takes one parameter (depth) to generate folders and files as described below: At depth 0, create a folder named 0, and inside it, create a file with its ...

Improving a lengthy TypeScript function through refactoring

Currently, I have this function that I am refactoring with the goal of making it more concise. For instance, by using a generic function. setSelectedSearchOptions(optionLabel: string) { //this.filterSection.reset(); this.selectedOption = optionLa ...

Link Google Map Marker Click Event with Dynamic Binding

I'm currently working on binding a click event to a link that is positioned outside the Google Map Canvas. The goal is to open an "infowindow" on a map marker when this link is clicked. While I know how to achieve this for a specific point, I need a d ...

Inline checkbox label with Bootstrap 5 styling

How can I align the checkbox with its label? Example <div class="row g-1 border-bottom p-3"> <div class="col border-end justify-content-center d-flex align-items-center"> <div class="h6 text-sm-center h-25&quo ...

Tips for displaying a modal within a modal in React

Currently, I have two components with modals. My goal is to open one modal from a button in the other component but clicking the button only closes the current active modal and doesn't open a new one. //Modal 1 <div className="modal fade" ...

Custom options in MUI Autocomplete are not displaying the selected option

I am currently implementing MUI v5's Autocomplete for a dropdown feature on my website. Within this dropdown, I have options that include both a title and an id. My goal is to store the selected option's id in the state while also updating the d ...

Struggling to make even the most basic example work with TypeScript and npm modules

After stumbling upon this repository that made using npm modules within a Typescript program look easy, I decided to give it a try by forking it and making some changes. My goal was to add another package to get a better understanding of the process. So, I ...

The redirection from HTTP or www to HTTPS is not functioning as expected

Redirecting all links to my website to the https:// domain is supposed to work flawlessly, but there are certain ways it doesn't quite function as expected. https://www.example.com --- works example.com --- works www.example.com --- encounters issu ...

Tips for deploying an Angular application with Node.js

Currently, I've set up a nodejs backend by following a tutorial to integrate tweets into the frontend of my application. As I prepare to deploy to a development server, I have successfully built the frontend using ng build --prod. However, I am facin ...

Assign the source property of the Handsontable dropdown option to match the related data value

I received a dynamic data array through an ajax call: data=[ // values are subject to change ['Alex', '16', ['2024-01-01,50000', '2024-03-01,20000', '2024-05-01,30000']], ['Bob&apos ...

Creating an If statement to evaluate the state of a parameter

In my simple Graphics User Interface, when the user clicks on "move", a yellow rectangle div moves across the screen. Now, I am trying to implement an event based on the position of the rectangle on the page. For example, if the div is at 400px (right), t ...

Show text using AJAX when the form is submitted

I'm in the process of creating a basic form with a submit button (see below). My objective is to allow users to enter text into the input box, click submit, and have the page refresh while displaying the entered text in a div element. The user's ...