Ari Seyhun
Ari Seyhun

Reputation: 12521

Render function on input removes reactivity in Vue

I'm trying to create a render function which renders an input field in Vue.

I can do this easily in a normal vue file with templates like so:

// NormalInput.vue
<template>
  <input :value="value" />
</template>

<script>
export default {
  name: "NormalInput",
  props: {
    value: null
  }
};
</script>

Note that the above does indeed work correctly.

But when trying to convert the above code into a render function with the following code:

// RenderFunctionInput.js
export default {
  name: "RenderFunctionInput",
  props: {
    value: null
  },
  render(createElement) {
    return createElement("input", {
      attrs: { value: this.value }
    });
  }
};

It seems reactive at first, but after editing the RenderFunctionInput manually, it stops being reactive. The Vue data seems to be updating but the actual value of the input does not.

You can view an example at https://codesandbox.io/embed/oooq7o2q16?module=%2Fsrc%2FApp.vue


Example screenshots:

I've created an example of the two components mentioned above. They are both using the same data value which is being incremented by 1 every 100 ms.

Screenshot 1

Screenshot 2

After typing in the NormalInput, it instantly gets overwritten by the :value="val" data. But when typing in the RenderFunctionInput, it stops incrementing and becomes detached from the data and becomes unreactive.

enter image description here

Upvotes: 3

Views: 1037

Answers (1)

Ari Seyhun
Ari Seyhun

Reputation: 12521

Instead of using attrs in the render function, you should use domProps.

As soon as the content of the input is edited, the attribute's value is still updated in the DOM (you can check your console) but that attribute is no longer relevant to what is being displayed

https://github.com/vuejs/vue/issues/9027#issuecomment-435797509


The render function should look like this instead:

// RenderFunctionInput.js
export default {
  name: "RenderFunctionInput",
  props: {
    value: null
  },
  render(createElement) {
    return createElement("input", {
      domProps: { value: this.value }
    });
  }
};

Upvotes: 3

Related Questions