Skip to content

Instantly share code, notes, and snippets.

@JeffreyWay
Last active February 26, 2021 22:11
Show Gist options
  • Star 27 You must be signed in to star a gist
  • Fork 12 You must be signed in to fork a gist
  • Save JeffreyWay/5c367388542e7c2ca421 to your computer and use it in GitHub Desktop.
Save JeffreyWay/5c367388542e7c2ca421 to your computer and use it in GitHub Desktop.
Vue.directive('ajax', {
params: ['complete'],
bind: function () {
this.el.addEventListener(
'submit', this.onSubmit.bind(this)
);
},
onSubmit: function (e) {
var requestType = this.getRequestType();
this.vm
.$http[requestType](this.el.action)
.then(this.onComplete.bind(this))
.catch(this.onError.bind(this));
e.preventDefault();
},
onComplete: function () {
if (this.params.complete) {
alert(this.params.complete); // Use pretty flash message instead.
}
},
onError: function (response) {
alert(response.data.message); // Use pretty flash message instead.
},
getRequestType: function () {
var method = this.el.querySelector('input[name="_method"]');
return (method ? method.value : this.el.method).toLowerCase();
},
});
new Vue({
el: 'body',
http: {
headers: {
// You could also store your token in a global object,
// and reference it here. APP.token
'X-CSRF-TOKEN': document.querySelector('input[name="_token"]').value
}
}
});
<form method="POST"
action="/posts/3"
v-ajax complete="Okay, the post has been deleted."
>
{{ method_field('DELETE') }}
{{ csrf_field() }}
<button type="submit">Delete Post</button>
</form>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.15/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-resource/0.6.1/vue-resource.min.js"></script>
<script src="/js/app.js"></script>
@janokary
Copy link

janokary commented Feb 6, 2016

An addition to also sumbit all form's inputs

I have a id on my forms so in the custom directive I added this method

    getFormDataById: function() {
//        return form data Using ID;
      var formId = this.el.id;
      var serializedData = $('#'+formId).serializeArray();
      var o = {};
      $.each(serializedData, function() {
          if (o[this.name] !== undefined) {
              if (!o[this.name].push) {
                  o[this.name] = [o[this.name]];
              }
              o[this.name].push(this.value || '');
          } else {
              o[this.name] = this.value || '';
          }
      });
      return o;
    }

that I call onSubmit

onSubmit: function (e) {
    var requestType = this.getRequestType();
    var formData = this.getFormDataById();
//          console.log(JSON.stringify(formData));
    this.vm
        .$http[requestType](this.el.action,formData)
        .then(this.onComplete.bind(this))
        .catch(this.onError.bind(this));
    e.preventDefault();
}

this way I pass all inputs

@socieboy
Copy link

I figure out pretty much as you have done but without use the ID in the form tag.

onSubmit: function (e) {
        e.preventDefault();
        this.el.querySelector('button[type="submit"]').disabled = true;
        this.vm.$http[this.getRequestType()](this.el.action, this.getFormData()) // Rename this because I don't need the ID anymore.
            .then(this.onComplete.bind(this))
            .catch(this.hasErrors.bind(this))
    },

    getRequestType: function(){
        var method = this.el.querySelector('input[name="_method"]');
        return (method ? method.value : this.el.method).toLowerCase();
    },
    getFormData: function() {
        // You can use $(this.el) in jQuery and you will get the same thing.
        var serializedData = $(this.el).serializeArray();
        console.log(serializedData);
        var objectData = {};
        $.each(serializedData, function() {
            if (objectData[this.name] !== undefined) {
                if (!objectData[this.name].push) {
                    objectData[this.name] = [objectData[this.name]];
                }
                objectData[this.name].push(this.value || '');
            } else {
                objectData[this.name] = this.value || '';
            }
        });
        return objectData;
    },

@janokary
Copy link

You are right @socieboy no id is needed after all.

@cmaas
Copy link

cmaas commented Mar 8, 2016

@janokary @socieboy

Thanks for the code. Food for thought: I'd use this merely as a fallback solution. After all, if we use Vue, there should be some kind of data model and thus, we could directly work with it via this.vm.$data. So basically like this:

this.vm.$http[requestType](this.el.action, this.vm.$data)... // add callbacks

@Leelam
Copy link

Leelam commented Mar 17, 2016

@janokary @socieboy I am getting this error TypeError: this.el.querySelector(...) is null at onSubmit

@plweil
Copy link

plweil commented Apr 7, 2016

@socieboy: Don't you have to somehow bind (this) to getFormData() ? E.g.,

.$http[requestType](this.el.action, this.getFormData()).bind(this)

Otherwise the console squawks that serializedData is undefined.

@0xlemi
Copy link

0xlemi commented May 14, 2016

Hello guys, how would you tackle showing validation errors?

I was thinking something like this but not sure how to make it work.

onError: function (response) {
    $.each(response.data, function(key, value){
        $this.el.querySelector('input[name="'+key+'"]').addClass('input-error-class');
    });
}

@cmnstmntmn
Copy link

i get

Uncaught TypeError: Cannot read property 'delete' of undefined

any ideea why ?

@cmnstmntmn
Copy link

cmnstmntmn commented Jun 13, 2016

solved.

i forget about Vue.use(VueResource);

@vijaythecoder
Copy link

vijaythecoder commented Sep 14, 2016

if you are ok to use formData
you could simply use this

        var formData = new FormData(this.el)
        this.vm.$http[this.getRequestType()](this.el.action, formData)
      //--------

@almaweb
Copy link

almaweb commented Oct 9, 2016

Hell,
Is any update of this gist for vue-2

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment