rakibtg
rakibtg

Reputation: 5901

Vue 2: Unable to find method on click event from component

In my vue app i am calling a function on click event, which is located in a component. Here is the component code:

Vue.component( 'new-board', {
  template: `
    <div>
      <br/>
      <div class="panel panel-primary">
        <div class="panel-heading">
          Create New Board
        </div>
        <div class="panel-body">
          <input class="form-control" placeholder="Board Name"/>
          <button 
            style="margin-top: 5px;" 
            @click.stop="addBoard"
            class="btn btn-success btn-xs btn-block"
          >
            Add Board
          </button>
        </div>
      </div>
    </div>
  `
} )

Here is the vue app instance:

var boardItem = new Vue( {
  el: "#board-item",
  data: {
    boards: [
      { name: 'learning vue 2' }
    ],
    newBoard: [],
    viewNewBoard: true
  },
  methods: {
    displayNewBoard: function() {
      event.preventDefault()
      if( this.viewNewBoard == false ) {
        this.viewNewBoard = true
      } else {
        this.viewNewBoard = false
      }
    },
    addBoard: function() {
      console.log( 'add board' )
    }
  }
} )

Now, when i click on the Add Board button from the above component, it is showing this error:

Uncaught ReferenceError: addBoard is not defined at click (eval at Xr (vue.min.js:7), :2:455) at HTMLButtonElement.invoker (vue.min.js:6)

It seems that the button from the component can't find the addBoard method, which is written in the same file! What i am missing here?

Upvotes: 0

Views: 3229

Answers (2)

deadPoet
deadPoet

Reputation: 538

A few changes here, if you want to share events with components that are not related you must use a new vue instance to fire those events and listen. So based on your code this should help.

window.Event = new Vue();

Vue.component( 'new-board', {
  template: `
    <div>
      <br/>
      <div class="panel panel-primary">
        <div class="panel-heading">
          Create New Board
        </div>
        <div class="panel-body">
          <input class="form-control" placeholder="Board Name"/>
          <button 
            style="margin-top: 5px;" 
            @click.stop="addBoard" // keep this as the name of the local method
            class="btn btn-success btn-xs btn-block">
            Add Board
          </button>
        </div>
      </div>
    </div>
  `,
   methods:{
        addBoard(){
             // fire the event, also you can add any params
             Event.$emit('callAddBoard',data)
        }
   }
} )

And the main instance should listen to that event

var boardItem = new Vue( {
  el: "#board-item",
  data: {
    boards: [
      { name: 'learning vue 2' }
    ],
    newBoard: [],
    viewNewBoard: true
  },
  methods: {
    displayNewBoard: function() {
      event.preventDefault()
      if( this.viewNewBoard == false ) {
        this.viewNewBoard = true
      } else {
        this.viewNewBoard = false
      }
    },
    addBoard: function() {
      console.log( 'add board' )
    }
  },

   created(){
         // here you listen and excute the remote event from component, and apply a local method.
         Event.$on('callAddBoard', this.addBoard)
   }
} )

As far as I tried this works , and you can send events to any component without the need of passing through the main instance.

Upvotes: 0

Bert
Bert

Reputation: 82439

Try:

Vue.component( 'new-board', {
  template: `
    <div>
      <br/>
      <div class="panel panel-primary">
        <div class="panel-heading">
          Create New Board
        </div>
        <div class="panel-body">
          <input class="form-control" placeholder="Board Name"/>
          <button 
            style="margin-top: 5px;" 
            @click.stop="addBoard"
            class="btn btn-success btn-xs btn-block"
          >
            Add Board
          </button>
        </div>
      </div>
    </div>
  `,
  methods: {
    addBoard: function(){ console.log('add board');}
  }
} )

Upvotes: 1

Related Questions