stencil icon indicating copy to clipboard operation
stencil copied to clipboard

bug: events lost when template separated out in another js file, view works

Open pranav-js opened this issue 3 years ago • 6 comments

Prerequisites

Stencil Version

2.11.0

Current Behavior

Interesting problem, so please read till the end. what I want to achieve is separating template in another js file and lazyload it when required. This same thing when done in React ecosystem works, but stencil doesn't!

I am having my tsx template in another .js file say

template-three.js has simple onClick which only alerts

import { h } from '@stencil/core';
export const template_three = () => {
  return <button onClick={() => alert()}>Template three here</button>;
};

when I try to call this method by importing in component-two.tsx like this

import { Component, Fragment, h, Host, State } from '@stencil/core';

@Component({
  tag: 'component-two',
  styleUrl: 'component-two.css',
  shadow: true,
})
export class ComponentTwo {
  @State() showComponentOne: any;
  method: any;
  template: string = '';

  constructor() {}

  componentWillRender() {
    this.fetchComp(2);
  }

// lazy load template when needed based on type passed

  fetchComp(type) {
    let this_ = this;
    switch (type) {
      case 0:
        import('./template').then(module => {
          this.showComponentOne = module.template_one;
        });
        break;
      case 1:
        import('./template-two').then(module => {
          this.showComponentOne = module.template_two;
        });
        break;
      case 2:
          import('./template-three').then(module => {
            this.showComponentOne = module.template_three;
          );
        break;
      default:
        break;
    }
  }

  clicked() {
    alert();
  }

  methodHere() {}

// check if template received then simply call that method with this attached

  render() {
    let this_ = this;
    return this.showComponentOne ? this.showComponentOne.apply(this) : <div></div>;
  }
}

View renders, but event listners are not working :/, not even a simple alert :(. When I inspect, I don’t see any event attached to button. however if same function I keep inside component class, it works :( !!!

check two different objects when template defined inside and outside component. $elem is null when template is in outside js

Can you tell me what I am doing wrong here.

I can’t keep templates in component only cause I have many UI’s for same logic. So far, I didn't get any way on internet this answer doesn't help either https://stackoverflow.com/questions/51984162/passing-custom-template-to-stencil-component

Expected Behavior

Events should get attached not just view.

Steps to Reproduce

written in description sample component and sample template. attached repo for triage.

Code Reproduction URL

https://github.com/pranav-js/triage-repo

Additional Information

React support separating templates out like this, not sure why stencil is loosing events. One thing I found is loss of $elem key in object returned probably by h

pranav-js avatar Dec 22 '21 05:12 pranav-js

Thanks for the issue! This issue has been labeled as holiday triage. With the winter holidays quickly approaching, much of the Stencil Team will soon be taking time off. During this time, issue triaging and PR review will be delayed until the team begins to return. After this period, we will work to ensure that all new issues are properly triaged and that new PRs are reviewed. In the meantime, please read our Winter Holiday Triage Guide for information on how to ensure that your issue is triaged correctly. Thank you!

ionitron-bot[bot] avatar Dec 22 '21 05:12 ionitron-bot[bot]

funny, I found a hack to make it work, but its super super strange and weird !!!!! 😰

I declared a random variable in my component and not event using it 😂. Just attach all events inside this random div tag without any function definition.

randomsds = (<div onClick={() => {}} onInput={() => {}}></div>)

and events inside external file template works now 🎉 .

Whoever reads this from community/helper/experts please explain me why?

next issue: now I have to do same for placeholder, id, style, class, basically attributes (but when I print object) it has image

pranav-js avatar Dec 22 '21 09:12 pranav-js

FYI I added a possible explanation (and workaround) on the StackOverflow question.

tricki avatar Jan 05 '22 13:01 tricki

@tricki that is still adding template1,2,3 in same .js file. with functional component however each one has its own .js file that i can lazy load

pranav-js avatar Jan 05 '22 13:01 pranav-js

@tricki @rwaskiewicz is there a way to store templates in CDN somewhere, since this is JSX I am not sure if I can send it from backend, if so how can i achieve that?

pranav-js avatar Jan 05 '22 13:01 pranav-js

Stencil doesn't have the same functionality that React does when it comes to functional components, which I think may be a part of what we're seeing here. At the very least, I think this is a good candidate where we can improve the documentation around functional components.

At the same time, the behavior we're seeing here (where onClick isn't firing) isn't intuitive, and should be looked into further when we dynamically import the module. Thanks for the detailed info, and thanks to @tricki for doing additional debugging!

rwaskiewicz avatar Jan 11 '22 15:01 rwaskiewicz