StencilJS Click method not getting called - stenciljs

while trying the example code from stenciljs doc - https://stenciljs.com/docs/templating-jsx, I'am facing one issue. The click event handler is not getting triggered at all.
import { Component, h } from '#stencil/core';
#Component({
tag: 'my-component',
shadow: true
})
export class MyComponent {
handleClick(event: UIEvent) {
alert('Received the button click!');
}
render() {
return (
<button onClick={ (event: UIEvent) => this.handleClick(event)}>Click Me!</button>
);
}
}
--index.html code--
<my-component></my-component>

You can try to use Polyfills in case that your Browser has issues with ES6 syntax e.g.
npm run build --es5

Related

How can I wrap a vue component during cypress component testing?

I am using component testing in Cypress on Vue. My project components use the vuetify plugin.
Currently, tested components load with Vuetify:
import DebuggingTemporaryComponent from "./DebuggingTemporaryComponent";
import {mount} from "#cypress/vue";
import vuetify from '../../resources/js/vuetify'
it('mounts the component with vuetify', () => {
mount(DebuggingTemporaryComponent,{vuetify,})
cy.contains('Hello World') ✅
}
However, the stylings are not functioning correctly because Vuetify components need to be wrapped in a <v-app> at least once on the page. In component testing this is not happening.
I need to customise the wrapper as suggested here in the docs for the React equivalent. However whenever I try to make my own function to do this, I get an error that the appropriate webpack loader isn't there. Vue loader is there and working.
import {mount as cypressMount} from '#cypress/vue'
export function mount (component){
return cypressMount(<v-app>component</v-app>, prepareComponent(props, options))
}
Can anyone help me with where to go next with this?
You can construct a simple wrapper in the test, for example
Component to test - Button.vue
<template>
<v-btn color="red lighten-2" dark>
Click Me
</v-btn>
</template>
Test
import Button from "./Button";
import {mount} from "#cypress/vue";
import vuetify from '../plugins/vuetify'
import { VApp } from 'vuetify/lib/components'
const WrapperComp = {
template: `
<v-app>
<Button />
</v-app>
`,
components: {
VApp,
Button
}
}
it('mounts the component with vuetify', () => {
mount(WrapperComp, { vuetify })
const lightRed = 'rgb(229, 115, 115)'
cy.contains('button', 'Click Me') // ✅
.should('have.css', 'background-color', lightRed) // fails if no <v-app> used above
})
You get an error because you are trying to use JSX which is indeed possible with Vue but you need to configure additional build plugins.
Same can be achieved without JSX by using render function
import {mount} from "#cypress/vue";
import vuetify from '../../resources/js/vuetify'
import { VApp } from 'vuetify/lib/components'
function mountComponentWithVuetify(componentToMount, options = {})
{
return mount({
render(h) {
return h(VApp, [h(componentToMount)])
}
},
{
vuetify,
...options,
})
}

How to listen events in react/angular/vue from stencils components

I have created simple one component in stencils.js and I used that in react/angular/vue. From my stencil component i have emit an event. This event is captured in angular/react/vue.
My problem is I need to use the same component twice in a single html. How I can identify the which event is emitted by which component instance ?
Using #stencil/react-output-target library and following this guide you will be able to do this:
//button component
import { Component, Prop, h } from '#stencil/core';
#Component({
tag: 'button-component',
styleUrl: 'button.css',
shadow: false,
scoped: true
})
export class MyComponent {
#Prop() label: string;
render() {
return <button type="button">{this.label}</button>;
}
}
// button component instance in React
<ButtonComponent label='Test Button' onClick={() => alert("Hi, I'm a button alert!")}/>
Just found it after hours of trying to pass a function inside of Stencil component...

Transition using this.router.push with tracking end of animation in VUE CLI

I really hope for your help! I'm a beginner, this is my first experience in creating web applications.
I work with Vue Cli, there is a lottie element that should be animated by click (I did it), then I should go to the “other page” (I did it) But, how do I implement the transition to the page only after the animation finishes? Help! You are welcome! For animation I use Anime.js
<script>
import { translate } from '../js/animate'
export default {
methods: {
go () {
translate(this.$refs.square)
this.$router.push('Comprestore')
}
}
}
</script>
/vue
<template>
<div id="animate" v-on:click = "go" ref="square">
<app-lottie></app-lottie>
</div>
</template>
<style scoped>
</style>
import anime from 'animejs'
export function translate (element) {
anime({
targets: element,
translateX: 500
})
}
You can use complete callback to wait until the animation is completed.
Now your code may looks like this:
...
go () {
translate(this.$refs.square, () => {
this.$router.push('Comprestore')
})
}
...
And
export function translate (element, callback) {
anime({
targets: element,
translateX: 500,
complete: callback
})
}
I create the example here.
In the example I also use page transition by using Vue built-in transition to transition between page. See Enter/Leave & List Transitions and Transitions in Vue Router.

Async Loading of Vue Component, $refs undefined in Mounted lifecycle

I have a simple button component that is asynchronously loaded into another component.
I have a call in mounted that references the button component but I get an error the it is undefined. If I import the button as you normally would there are no issues. I am attempting to load as asynchronously as I have other points where I would call the button however in this case it should be ready to go on mounted.
It was my understanding that vue will load the component when you need it however I need it on mounted but can not access it. Am OI going about this wrong? Maybe I don't completely understand it all yet.
**error**
Error in v-on handler: "TypeError: Cannot read property '$el' of undefined"
**code**
<template>
<div class"wrapper">
<button ref="flipBtn" /> I am the text </button>
</div>
</template>
// Works if I import this way
// import button from '#/components/inline-components/button'
export default {
components: {
// button
button: () => { import ('#/components/inline-components/button') }
},
mounted() {
// I have tried wrapping in a this.$nextTick(() => {}) but no luck
this.$refs.flipBtn.$el.focus({ preventScroll: true })
}
}
Thanks to #HusamIbrahim suggestions I was able to get rid of the error by using both a custom directive and a conditional check of the $refs in a later function call
**error**
Error in v-on handler: "TypeError: Cannot read property '$el' of undefined"
**code**
<template>
<div class"wrapper">
<button ref="flipBtn" v-focus /> I am the text </button>
</div>
</template>
// Works if I import this way
// import button from '#/components/inline-components/button'
export default {
components: {
// button
button: () => { import ('#/components/inline-components/button') }
},
directives: {
focus: {
inserted: function (el) {
el.focus()
}
}
}
methods {
// Wasn't apart of my original question but I was able to remove the error on it using comments above.
glideAfter () {
// Give Flip button focus, Hidden button that helps with keyboard focus
if (this.$refs && this.$refs.flipBtn) {
this.$refs.flipBtn.$el.focus({ preventScroll: true })
}
}
}

`v-on:click` bind to function in module

I am totally new to Vuejs and my question is:
Is there anyway for v-on to listen on click event, then execute a function which is defined in a module?
For example:
<button v-on:click="executeClick()"></button>
Will execute executeClick() in below module, which will be imported to Vue instance through require:
module.exports = {
executeClick: function () {
// do something
}
}
I am trying to keep vue instance's methods not to be crowded with a bunch of functions.
No, within the model you need features that are in this your component
soluction:
click.js
module.exports = {
executeClick: function () {
}
}
component.vue
<template>
<tag #click="$options.click.executeClick">
</template>
<script>
import click from 'click.js'
export default {
click: click
}
</script>