2

I wrote a functional component that compiles form fields for certain conditions. The form fields are their own component. So I have three levels:

<FormComponent>          // handles input events
  <FunctionalComponent>  // selects form fields
    <FormFieldComponent> // emits input events
  </FunctionalComponent>
</FormComponent>

Functional components have no this, but get a context object as argument to the render function. What I could do is using context.data.on[eventName](event) or some similar construct. I also know that I could use an event bus or the dom elements directly, like described here.

All this looks rather dirty to me. Is there any this.$emit equivalent in functional components?

tony19
  • 125,647
  • 18
  • 229
  • 307
koehr
  • 769
  • 1
  • 8
  • 20
  • Are you saying you want your FunctionalComponent to bubble events from your FormFieldComponent to your FormComponent? – Roy J Jun 01 '17 at 17:52
  • 2
    https://github.com/vuejs/vue/issues/3348 – Roy J Jun 01 '17 at 17:55
  • Yes, that is it! It took me a minute to wrap my head around it but that should solve my problem. Thanks a lot @RoyJ – koehr Jun 02 '17 at 08:41

2 Answers2

1

Thanks to @RoyJ 's comment, I was able to solve my problem. Here for everyone who may face the same problem:

As described in a github issue, the second argument for the render function has a data object that contains all the listeners and more. So the easiest way is to just directly give it to the child component:

render(h, context) {
  return h(FormFieldComponent, context.data, children)
}

In my specific case, I only take the listeners directly, because I manipulate large parts of the data object:

render(h, context) {
  const data = createDataObject()
  data.on = context.data.on

  return h(FormFieldComponent, data, children)
}
koehr
  • 769
  • 1
  • 8
  • 20
0

This is how it looks a functional component emitting an event:

export default {
  functional: true,
  render(createElement, { listeners }) {
    return createElement(
      "button",
      {
        on: {
          click: event => {
            const emit_event = listeners.event_from_child; //> the name is: event_from_child
            emit_event("Hello World!Is this the message we excpected? :/");
          }
        }
      },
      "Pass event to parent"
    );
  }
};

And listening to the parent component:

<functional-component @event_from_child="event_from_child"></functional-component>

See it in action here

Roland
  • 24,554
  • 4
  • 99
  • 97