简体   繁体   中英

How to trigger Stencil component function/method from outside Vue instance

Is there any possibility to trigger Stencil compontent function from parent Vue instance?

I would like to, for example, run callChild() method in Vue instance, that will trigger doSomething() in Stencil component.

Main, html file with vue code file, which contains stencil component:

<body>
    <div id="app">
      <test-component :rules="[required, passwordRule]" :placeholder="placeholder" :label="label" :value="value" @valueChange="e => onValueChange"></test-component>
      {{value}}
      <button @click="foo()">Test</button>
    </div>
  </body>
  <script>
    var app = new Vue({
      el: '#app',
      data() {
        return {
          label: 'Nazwa Użytkownika',
          value: '',
          placeholder: 'Wpisz nazwę użytkownika',
          required: v => !!v || 'This field is required',
          passwordRule: v => v.length >= 8 || 'Your password is too short',
        };
      },
      methods: {
        callChild() {
          //this function should trigger bar() function in stancil <test-component>
        },
        onValueChange(e) {
          console.log(e);
        },
      },
    });
  </script>

Stencil component code:

import { h, Component, Element, Event, EventEmitter, State, Watch, Prop, Method } 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() rules: Array<Function>;
  @Prop() placeholder: string;
  @Prop({ mutable: true }) value: string;
  @Prop() hidedetails: boolean;
  @Event() valueChange: EventEmitter;

  @State() errorDetails: any;
  @State() showError: boolean = false;

  @Watch('value')
  watchHandler(newValue: string, oldValue: string) {
    console.log('The new value of activated is: ', newValue, 'Old val: ', oldValue);
    console.log(this.required(newValue));
    if (this.required(newValue) != true) {
      this.errorDetails = this.required(newValue);
      this.showError = true;
    } else {
      this.showError = false;
    }

    console.log(this.rules);
  }

  required = v => !!v || 'This field is required';

  @Method()
  async testClick(val) {
    await console.log(val);
  }

  @Method()
  doSomething() {
    //do something
  }

  handleChange(event) {
    const val = event.target.value;
    console.log(val);
    this.value = val;
    this.valueChange.emit(val);
  }
  render() {
    if (this.hidedetails) {
      return (
        <div>
          <label>
            {this.label}
            <div>
              <input placeholder={this.placeholder} value={this.value} onInput={event => this.handleChange(event)}></input>
            </div>
          </label>
        </div>
      );
    } else {
      return (
        <div>
          <label>
            {this.label}
            <div>
              <input placeholder={this.placeholder} value={this.value} onInput={event => this.handleChange(event)}></input>
              <div class="error-details">
                <div class={this.showError ? 'text-active' : 'text-inactive'}>{this.errorDetails}</div>
              </div>
              <button onClick={this.testClick}>Kilknij mnie!</button>
            </div>
          </label>
        </div>
      );
    }
  }
}

Ok - the answer is simple. You need to use ref. Just add ref tag to element in html:

<test-component ref="form" :rules="[required, passwordRule]" :placeholder="placeholder" :label="label" :value="value" @valueChange="e => onValueChange"></test-component>

And then Vue method should look like:

foo() {
          this.$refs.form.bar();
        },

Where bar() is exactly name of method in Your Stencil component.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM