3
votes

I'm trying to display a string in reverse, using Vue. My template is:

<div id="app">
  <reverse :msgreverse="message" :reverseMessage="reverseMessage()"></reverse>
</div>

And my script:

function reverseMessage(msg) {
  return msg.split('').reverse().join('')
}

Vue.component('reverse', {
  props:["msgreverse", "reverseMessage"],
  template: '<p v-html="reverseMessage(msgreverse)"></p>'
})

var app = new Vue({
  el: '#app',
  data: {
    message:'The message to reverse !',
  }
})

This fails with the following console errors:

  • TypeError: reverseMessage is not a function. (In 'reverseMessage()', 'reverseMessage' is undefined)

  • Error in render: "TypeError: reverseMessage is not a function. (In 'reverseMessage()', 'reverseMessage' is undefined)"

  • Property or method "reverseMessage" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property

How do I get the <reverse> component to display a given string in reverse?

1
Your reverseMessage function has to be defined as your Vue instance method inside of methods: {}. Check if that works. Also, isn't it better to define it in your reverse component and call it there (without the prop)? It's what's that component is for after all.dziraf

1 Answers

6
votes

The errors you're seeing are due to the fact that Vue is not aware of the global function you've defined (i.e., reverseMessage()). Vue does not provide access to global functions/variables when rendering templates. The local functions it has access to are declared in the component's methods property. In your case, it would look like this:

Vue.component('reverse', {
  // ...
  methods: {
    reverseMessage(msg) {
      return msg.split('').reverse().join('')
    }
  }
})

Since it seems that component's purpose is to reverse the given string, there's no need to specify a prop for the reverseMessage function, so you can remove it from props:

Vue.component('reverse', {
  // ...
  //props:["msgreverse", "reverseMessage"],  // DON'T DO THIS
  props:["msgreverse"],
})

Your template uses the v-html directive to show the reversed message, but that's unnecessary because (1) the message itself is not HTML, and (2) Vue recommends against it for user input:

Dynamically rendering arbitrary HTML on your website can be very dangerous because it can easily lead to XSS vulnerabilities. Only use HTML interpolation on trusted content and never on user-provided content.

Instead, you should use string interpolation for this:

Vue.component('reverse', {
  // ...
  //template: '<p v-html="reverseMessage(msgreverse)"></p>'  // DON'T DO THIS
  template: '<p>{{reverseMessageg(msgreverse)}}</p>'
})

Vue.component('reverse', {
  props: ['msgreverse'],
  methods: {
    reverseMessage(msg) {
      return msg.split('').reverse().join('')
    }
  },
  template: '<p>{{reverseMessage(msgreverse)}}</p>'
})

new Vue({
  el: '#app',
  data: () => ({
    message: 'Hello Vue.js!',
  }),
})
<script src="https://unpkg.com/[email protected]"></script>

<div id="app">
  <reverse :msgreverse="message"></reverse>
</div>