Simon Cooper
Simon Cooper

Reputation: 1594

Vue Multiselect is not submitting ID value (Rails API)

My app is a Rails API backend and VueJS via Nuxt front end.

I have a form where one of the inputs is a select and I'm using vue-multiselect. The select options are values from a different table, where I want to display the name field, but submit the ID.

I am able to display the options in the drop drown ok, and I'm also submitting other values in the form, but the ID is not working.

Rails console shows the error of distillery_id not being a permitted parameter, although I do have this set in the controller.

Started POST "/api/v1/gins" for ::1 at 2019-02-01 13:25:38 +0000
Processing by Api::V1::GinsController#create as HTML
  Parameters: {"gin_name"=>"distillery_id", "description"=>"distillery_id should be submitted", "distillery_id"=>{"id"=>3, "distillery_name"=>"Gordon's", "snippet"=>nil, "description"=>nil, "website"=>nil, "country"=>"United Kingdom", "created_at"=>"2019-01-29T13:46:15.088Z", "updated_at"=>"2019-01-29T13:46:15.088Z", "slug"=>nil}, "abv"=>"0", "snippet"=>"distillery_id now?", "gin"=>{"gin_name"=>"distillery_id", "snippet"=>"distillery_id now?", "description"=>"distillery_id should be submitted", "abv"=>"0", "distillery_id"=>{"id"=>3, "distillery_name"=>"Gordon's", "snippet"=>nil, "description"=>nil, "website"=>nil, "country"=>"United Kingdom", "created_at"=>"2019-01-29T13:46:15.088Z", "updated_at"=>"2019-01-29T13:46:15.088Z", "slug"=>nil}}}
Unpermitted parameter: :distillery_id

gins_controller.rb

...
    def gin_params
      params.require(:gin).permit(:gin_name, :alcoholic, :snippet, :description, :abv, :distillery_id)
    end
...

new.vue

<template>
  <section class="container">
    <div>
      <h1>Gins</h1>
      <form @submit.stop.prevent="addGin">
        <h2>New Gin</h2>
        <p>
            <label for="gin_name" class="input-label">Title:</label>
            <input id="gin_name" v-model="gin_name" type="gin_name" name="gin_name" class="input">
        </p>
        <p>
            <label for="snippet" class="input-label">Snippet:</label>
            <input id="snippet" v-model="snippet" type="text" name="snippet" class="input">
        </p>
        <p>
            <label for="description" class="input-label">Description:</label>
            <input id="description" v-model="description" type="textarea" name="description" class="input">
        </p>
        <p>
            <label for="abv" class="input-label">ABV%:</label>
            <input id="abv" v-model="abv" type="number" name="abv" class="input">
        </p>
          <div>
            <label for="distillery_id" class="input-label">Distillery:</label>
            <multiselect
                v-model="distillery_id"
                track_by="distillery_id"
                :options="options"
                :searchable="true"
                placeholder="Choose One Distillery"
                :custom-label="label"
                >
            </multiselect>
        </div>
        <p>
            <input type="submit" value="Submit" class="button">
        </p>
      </form>
    </div>
  </section>
</template>
<script>
import axios from 'axios'
import Multiselect from 'vue-multiselect'

export default {

  components: { Multiselect },
  data() {
    return {
      gin_name: '',
      snippet: '',
      description: '',
      abv: '',
      distillery_id: '',
      options: []
    }
  },

  mounted() {
    this.getDistilleries()
  },

  methods: {

    label(option) {
      return `${option.distillery_name}`
    },

    addGin() {
      axios.post('http://localhost:4000/api/v1/gins', {
        gin_name: this.gin_name, description: this.description, distillery_id: this.distillery_id, abv: this.abv, snippet: this.snippet
      })
        .then((response) => {})
      console.log()
    },
    getDistilleries(req) {
      axios.get('/api/v1/distilleries')
        .then((res) => {
          this.options = res.data
        })
        .catch((error) => {
          console.log(error)
        })
    }

  }
}
</script>
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>
<style>

</style>

Based on the console, I suspect this is a rails issue rather than vue, but that permitted params looks good to me.

Any suggestions what else could be amiss?

Upvotes: 0

Views: 371

Answers (2)

Rob Nice
Rob Nice

Reputation: 298

Caution, this is untested. But, after having a quick look at VueMultiselect's docs and your Vue component, it looks like your distillery_id v-model is being set to a single distillery object. Which I believe @UdAY revealed in the comments. So your POST data can be changed to:

addGin() {
  axios.post('http://localhost:4000/api/v1/gins', {
    gin_name: this.gin_name,
    description: this.description,
    distillery_id: this.distillery_id.id, //this.distillery_id is being set as an object and you just need the id prop here
    abv: this.abv, snippet: this.snippet
  })

Upvotes: 1

Juanmabs22
Juanmabs22

Reputation: 1300

Have you tried to use a filter to get the good values?

 addGin() {
  let myId = options.filter(o => distillery_id.some(d => d.distillery_id === o.distillery_id));
  axios.post('http://localhost:4000/api/v1/gins', {
    gin_name: this.gin_name, 
    description: this.description, 
    distillery_id: myId, 
    abv: this.abv, 
    snippet: this.snippet
  }).then(console.log)
},

I'm not sut that this works, check the code before use.

Other way is debug the code in the line and check how you could get the id:

 addGin(argument1, argument2, argument3) {
  debugger; // The code will stop here, check this object to get the data and change the code!
  axios.post('http://localhost:4000/api/v1/gins', {
    gin_name: this.gin_name, 
    description: this.description, 
    distillery_id: this.distillery_id, 
    abv: this.abv, 
    snippet: this.snippet
  }).then(console.log)
},

I suggest to change multiselect to vue-select The docs seems more readable.

Hope it helps :)

Upvotes: 0

Related Questions