The Stencil EventEmitter fails to send data to the Vue instance

Attempting to develop a custom component using Stencil with an input feature. The goal is to create a component with an input field that, upon value change, emits the input to the Vue instance and logs this event to the console (later updating the value in the Vue instance). However, after altering the input value in Stencil, no changes occur.

While exploring how Stencil components functioned, I referenced the following resources:

https://medium.com/@cindyliuyn/create-a-stencil-form-input-component-for-angular-and-vue-js-22cb1c4fdec3

In an attempt to address the issue, I also consulted:

https://medium.com/sharenowtech/using-stenciljs-with-vue-a076244790e5

HTML and Vue code:

<!DOCTYPE html>
<html dir="ltr" lang="en">
  <head>
    <meta charset="utf-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0, minimum-scale=1.0, maximum-scale=5.0" />
    <title>Stencil Component Starter</title>
    <script src="https://unpkg.com/vue"></script>
    <script type="module" src="/build/vox-wc-research.esm.js"></script>
    <script nomodule src="/build/vox-wc-research.js"></script>
  </head>
  <body>
    <div id="app">
      <test-component :placeholder="placeholder" :label="label" :value="value" @valueChange="e => onValueChange"></test-component>
      {{value}}
    </div>
  </body>
  <script>
    var app = new Vue({
      el: '#app',
      data: {
        label: 'Username',
        value: '',
        placeholder: 'Enter username',
      },
      methods: {
        onValueChange(e) {
          console.log(e);
        },
      },
    });
  </script>
</html>

Stencil Component:

import { h, Component, Element, Event, EventEmitter, Prop /* PropDidChange */ } from '@stencil/core';
@Component({
  tag: 'test-component',
  styleUrl: 'test-component.css',
  //shadow: true,
})
export class FormInputBase {
  @Element() el: HTMLElement;
  @Prop() type: string = 'text';
  @Prop() label: string;
  @Prop() placeholder: string;
  @Prop({ mutable: true }) value: string;
  @Event() valueChange: EventEmitter;

  handleChange(event) {
    const val = event.target.value;
    console.log(val);
    this.value = val;
    this.valueChange.emit(val);
  }
  render() {
    return (
      <div>
        <label>
          {this.label}
          <div>
            <input placeholder={this.placeholder} value={this.value} onInput={event => this.handleChange(event)}></input>
            {this.value}
          </div>
        </label>
      </div>
    );
  }
}

Answer №1

Vue does not natively support camel-case event names as all event listeners using v-on: are automatically converted to lower-case (check out https://v2.vuejs.org/v2/guide/components-custom-events.html#Event-Names for more information).

However, when loading your component(s), you can utilize Stencil's defineCustomElements options to "transform" your event names:

import { applyPolyfills, defineCustomElements } from 'my-component/loader';

applyPolyFills().then(() => {
  defineCustomElements({
    ce: (eventName, opts) => new CustomEvent(eventName.toLowerCase(), opts)
  });
});

If you want to see a more detailed example, you can refer to the source code of Ionic Framework:

https://github.com/ionic-team/ionic-framework/blob/b064fdebef14018b77242b791914d5bb10863d39/packages/vue/src/ionic-vue.ts

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

"Implementing conditional rendering to hide the Footer component on specific pages in a React application

Is there a way to conceal the footer component on specific pages? app.js <div className="App"> <Header setShowMenu={setShowMenu} /> {showMenu ? <Menu navigateTo={navigateTo} setShowMenu={setShowMenu} /> : null} <Main na ...

An easy way to adjust the date format when linking a date in ng-model with md-datepicker

<md-input-container> <label>Scheduled Date</label> <md-datepicker ng-model="editVersionCtrl.selectedPlannedDate" ng-change="editVersionCtrl.checkPlannedDate()"> </md-datepicker> </md-input-container> ...

Tips for accessing the value of the range slider in Bootstrap 5 while it is being slid

Is it possible to capture the value from a Bootstrap 5 slider while sliding? I want to continuously receive the value as I move the handle, rather than only getting the final value when I release the handle. Currently, I am using a Bootstrap 5 range slide ...

An unusual problem stemming from jQuery/AJAX arises when variables within a function fail to update while a click

I've been struggling with a small issue for the past three days that I just can't seem to resolve. It doesn't seem to be a coding error, but rather a misunderstanding of variables and why the onClick event isn't functioning properly. H ...

Is there a way to enhance this Java script file reader into a multi-file reader?

I am seeking assistance with JavaScript as it is not my strong suit, but I require it for my website. My goal is to be able to read the files that I select. Below you can find the input form: <form name="filUpload" action="" method="post" enctype="mul ...

React Component - Element with an undefined value

When I tried implementing an Ionic Modal as a React Component, I encountered the following error message: Type '({ onClose, tipo }: PropsWithChildren<{ onClose: any; tipo: number; }>) => Element | undefined' is not assignable to type & ...

"Surprising outcomes when using the splice method on an array

Exploring the functionalities of Array.splice(). deleteCount: A whole number indicating the quantity of old array elements to eliminate. Understood. It seems clear. I aim to extract the final 4 items in the array. I trust that refers to elements? arr. ...

Receiving a 401 error while attempting to make an axios get request with authentication headers

I have been utilizing axios in my React project to fetch data from MongoDB. However, I am facing a challenge with the axios get requests returning a 401 error when I include my auth middleware as a parameter. This middleware mandates that the user must pos ...

What is the best way to arrange images in a 3 by 3 grid, beginning at position 0, using JavaScript to control navigation through button clicks?

When I click on button 1, it starts at image 1 because the counter is set to 0. Clicking on button 2 takes me to image 4 with a counter value of 3, while clicking on button 3 leads to image 7 with a counter value of 6. The process should also work in reve ...

What is the best way to locate a table of a specific class using jQuery selectors?

Is there a way to specifically target a table with the class "d" using jQuery selectors? I'm having trouble making it work... var dTableTags = $(".d table"); For instance, an example table would look like this... <table id="thetable" class="d"&g ...

Update the VueJS application by loading and replacing the existing JSON data with new information

Is there a way to dynamically re-render the entire v-for loop and DOM after fetching and loading new JSON data to replace the current one? I want to be able to click on different options and have the products updated. Vue.use(VueResource); var produ ...

Switching URLs or internal pages using jQuery Mobile's select menu feature

Utilizing a select box as the navigation menu for my jQuery Mobile website. Some menu items link to internal pages while others link to external URLs. This is the code I'm using to change the page URL: $('#menu-select').change(function() ...

Preventing undesired form submissions in HTML and JavaScript

My question might be simple, but it's what I have in mind. When working with two buttons in HTML - one for form submission and the other to trigger a JavaScript event - both buttons end up submitting the form. How can I make sure the second button onl ...

Efficiently capturing selections from a Dynamic Dropdown menu and storing them in a database using VueJs and Laravel

I have been working on developing a form where users can add cities based on the countries selected from a dynamic drop-down menu. While I managed to extract the category_id (foreign key) in Vue.js, I am struggling with passing it to the Laravel backend. ...

Tips for retaining the selected radio button in a Java web application even after a page refresh

As someone new to web development using the Stripes Framework, I am encountering an issue with radio buttons on a webpage. When one of the radio buttons is selected, a text box and Submit Button appear. After clicking the Submit button, the functionality ...

Repeating the setTimeout function in a loop

I've been delving into JavaScript and trying to understand it better. What I'm aiming for is to have text displayed on the screen followed by a countdown sequence, like this: "Test" [1 second pause] "1" [1 second pause] "2" [1 second pause ...

Recursive routing in NodeJS using Express

Certain website APIs have the capability to perform actions such as: Initial user's id their first friend, also a user v v GET /api/users/54282/friends/0/friends/0 ...

Is it possible to target elements within a UMAP iframe using CSS?

I have integrated a uMap map into my website. Here is the code: <iframe id="umapiframe" class="iframe-umap" width="100%" height="300px" frameborder="0" allowfullscreen src="//umap.openstreetmap.fr/f ...

Ways to obtain an attribute through random selection

Figuring out how to retrieve the type attribute from the first input element: document.getElementById('button').addEventListener('click', function() { var type = document.querySelectorAll('input')[0].type; document.getE ...

Tips for generating AJAX requests directly from HTML documents

Hey there! I'm fairly new to JavaScript and have a question that might seem silly to some. How exactly can I invoke a function from a Coffeescript file within my HTML code? I'd like to give users the option to choose the language in which they v ...