1

I have a route setup like this:

Route::post('subjects/{subject}/{tag}', 'TagController@show');

And I have the following form structure, where I am populating the options of a select element by looping through a $tags array:

<form id="tagForm" method="POST"
action="/subjects/{{ $lesson->subject->slug }}/{{ 'selected option will go here' }}">
    {{ csrf_field() }}
   <div class="select">
      <select @change="onTagSelected">
        <option>Tags</option>
        @foreach ($tags as $tag)
                <option value="{{ $tag->id }}">{{ $tag->title }}</option>
        @endforeach
      </select>
    </div>
</form>

How can I change the form action according to the currently selected tag from the option?

I am using Vue.js as js framework and I am listening for onchange event:

onTagSelected: function(event) {
        var tagForm = document.getElementById('tagForm');
// what should I do here to change the action?
        tagForm.submit();
}
2
  • You need JavaScript for that if I understand you correctly Commented Dec 8, 2017 at 18:30
  • Yes, I forgot to mention that I am using vuejs as js framework. And if you look at the select tag, you will see that I have already attached an event listener. I just don't know what to do in there in order to change the action and then submit it Commented Dec 8, 2017 at 18:34

2 Answers 2

1

The way that you've solved it, you're not really using VueJS, and flat javascript would make more sense. A more VueJS approach would be something like this: (presuming you're writing in a Blade View, this would need to be in a )

new Vue({
   data: function() {
      return {
         form: {
             baseAction: "/subjects/{{ $lesson->subject->slug }}/",
             chosenAction: '',
         }
      }
   },
   computed: {
       computedAction: function() {
           return this.form.baseAction + this.form.chosenAction;
       }
   }
});

Now for your form:

<form action="computedAction">

And for your select:

<select v-model="form.chosenAction">

The onchange isn't necessary here as we're binding the value of the selected to the chosenAction property of the form object. We then use the computedAction property (which is a computed value, of course) to dictate the action of our form.

EDIT - When using a transpiled vuejs approach with single file components:

If you want vuejs to be responsible for the life-cycle of the form, then you can use a single file component:

<template>
    <form id="tagForm" method="POST" action="computedAction">
        <input type="hidden" name="_token" value="token"/>
        <div class="select">
            <select v-model="form.chosenAction">
                <option value="">Tags</option>
                <option v-for="tag in tags" value="tag.id"> {{tag.title}} </option>
            </select>
        </div>
     </form>
</template>

<script>
    export default {
        props: ['tags', 'slug', 'token']
        data: function() {
            return {
               form: {
                   chosenAction: ''
               }
            }
       },

       computed: {
           computedAction: function() {
               return `/subjects/${slug}/${this.form.chosenAction}`
           }
       }
    }
</script>

Now in your app.js file you need to tell Vue about this new component so you can use it in your blade template. This needs to come after you use import Vue from 'vue' in your app.js file.

import MyCoolForm from './path/to/my/cool/form.js';

Vue.component('v-mycoolform', MyCoolForm);

Now in your blade template, you can pass properties to this component:

<v-mycoolform :slug="{{$lesson->subject->slug}}" :token="{{csrf_token()}}" :tags="{{json_encode($tags)}}"/>
Sign up to request clarification or add additional context in comments.

9 Comments

How can I attach {{ $lesson->subject->slug }} to the baseAction property? You are directly referring the blade syntax in vue, I have to send the value of it from blade to vue. How can I do that?
@Eisenheim Is your Vue in a separate file, not inside of a <script> block in a blade template?
Yes, separated. in app.js file. I am thinking of something like this: <select @change="onTagSelected({{ $lesson->subject->slug }})" v-model="form.chosenAction"> And then maybe I can append the value to baseAction?
@Eisenheim K, sec
@Eisenheim Added the single file approach
|
0

I had to bind the select tag to a v-model property:

<form id="tagForm" method="POST" action="/subjects/{{ $lesson->subject->slug }}/">
    {{ csrf_field() }}
   <div class="select">
      <select @change="onTagSelected" v-model="selectedTag">
        <option>Tags</option>
        @foreach ($tags as $tag)
            <option value="{{ $tag->id }}">{{ $tag->title }}</option>
        @endforeach
      </select>
    </div>
</form>

And in my event listener, I am appending the property to the action and then submitting it:

onTagSelected: function(event) {
        var tagForm = document.getElementById('tagForm');
        tagForm.action += this.selectedTag;
        // console.log(tagForm.action);
        tagForm.submit();
}

Although this solves my problem, but I am not happy with it. I think there is better way to do this. Please feel free to share the best solution for circumstances like this.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.