0

I followed along this tutorial and it worked perfectly fine. But what I want is to not use submit button to check or perform the validation, what I want is while I'm typing, it is now validating the form. Please see my code below, or visit the link that I mentioned above.

Code:

routes

<?php

Route::get('/', function () {
    return view('welcome');
});

Route::get('/article/create', 'ArticleController@showArticleCreationForm');
Route::post('/article', 'ArticleController@publish');



ArticleController

<?php
namespace App\Http\Controllers;

use Illuminate\Http\Request;
use App\Http\Requests;
use App\Http\Controllers\Controller;

class ArticleController extends Controller
{
    public function showArticleCreationForm(){
        return view('article.create');
    }

    public function publish(Request $request){
        $this->validate($request, [
            'title' => 'required|min:3',
            'body' => 'required|min:10'
        ]);
        if ($request->ajax()) return;

        return 'publish';
    }
}



create.blade.php

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Create Article</title>
    <link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css" rel="stylesheet" integrity="sha256-7s5uDGW3AHqw6xtJmNNtr+OBRJUlgkNJEo78P4b0yRw= sha512-nNo+yCHEyn0smMxSswnf/OnX6/KwJuZTlNZBjauKhTK0c+zT+q5JOCx0UFhXQ6rJR9jg6Es8gPuD2uZcYDLqSw==" crossorigin="anonymous">
    <style>
        .body {
            height: 200px !important;
        }

        .error {
            color: darkred;
            margin-top: 5px;
            display: block;
        }
   </style>
</head>
<body id="app">
    <form @submit.prevent="submitForm" class="col-md-4 col-md-offset-4" action="{{ URL::to('/') }}/article" method="post">
        <h1>Create New Article</h1>
        <hr>

        {!! csrf_field() !!}

        <div class="form-group">
            <input class="form-control title" type="text" name="title" placeholder="Title" v-model="formInputs.title">
            <span v-if="formErrors['title']" class="error">@{{ formErrors['title'] }}</span>
        </div>

        <div class="form-group">
            <textarea class="form-control body" name="body" placeholder="Content" v-model="formInputs.body"></textarea>
            <span v-if="formErrors['body']" class="error">@{{ formErrors['body'] }}</span>
        </div>

        <button class="btn btn-primary" type="submit">Publish</button>
    </form>


<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/1.0.14/vue.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue-resource/0.6.1/vue-resource.min.js"></script>
<script>
    new Vue({
        el: '#app',

        data: {
            formInputs: {},
            formErrors: {}
        },

        methods: {
            submitForm: function(e){
                var form = e.target;
                var action = form.action;
                var csrfToken = form.querySelector('input[name="_token"]').value;

                this.$http.post(action, this.formInputs, {
                  headers: {
                      'X-CSRF-TOKEN': csrfToken
                  }
                })
                .then(function() {
                      form.submit();
                })
                .catch(function (data, status, request) {
                  var errors = data.data;
                  this.formErrors = errors;
                });
            }
        }
    });
</script>
</body>
</html>
2
  • If you want validation (which is ajax) with onenter then you might also want to do it with some debounce. Then it's fine. Just decouple article creation from validation and create additional route for just validation. Commented Jul 27, 2017 at 7:56
  • @dfsq Hi. Can you provide your answer explicitly? Commented Jul 27, 2017 at 8:03

1 Answer 1

1

If you want to validate while typing you should add an @keyup (or v-on:keyup) event listener on your inputs and validate when it's triggered e.g:

<input class="form-control title" type="text" name="title" placeholder="Title" v-model="formInputs.title" v-on:keyup="validate">

And your event listener:

 methods: {
      validate: function (e) {
            //e.target would have the target input which is being changed 

            _.debounce(function () {
                    var input = e.target;
                    var form = input.form;
                    var action = form.action; 
                    var csrfToken = form.querySelector('input[name="_token"]').value;

                    this.$http.post(action, this.formInputs, {
                    headers: {
                        'X-CSRF-TOKEN': csrfToken
                    }
                 })
                .then(function() {
                      // Don't submit
                 })
                .catch(function (data, status, request) {
                    var errors = data.data;
                    this.formErrors = errors;
                });

            }.bind(this), 500); 
      }

This example uses _.debounce which is a lodash function but you can easily write something similar yourself via setTimeout and cancelTimeout (lodash is just a convenience). The purpose is to not trigger validation on every keyup but rather spread it around a bit.

Sign up to request clarification or add additional context in comments.

10 Comments

Hi. Is there any other way than this? so I can still use the submitForm method that I've created?
You can use the same method, but just not call .submit if it passes. Check the update.
ReferenceError: _ is not defined and TypeError: e is undefined
This example uses _.debounce which is a lodash function but you can easily write something similar yourself via setTimeout and cancelTimeout (lodash is just a convenience). The purpose is to not trigger validation on every keyup but rather spread it around a bit. I did mention this.
You'd need to modify your publish function to only validate the field you give it. However you should consider using a Vue validation library like e.g. github.com/kazupon/vue-validator
|

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.