Laravel & VueJS: Calling a VueJS Method Inside Blade - laravel

I'm new to Laravel & VueJS so sorry in advance for the messed up code.
I've been trying to make a registration form with VueJS being integrated into laravel to make it more dynamic.
Now I've been trying to use the # infront of the {{ }} to show laravel i'm trying to integrate VueJS but instead of VueJS responding to this it just plainly prints : {{ error }} or {{ checked ? "yes" : "no" }}.
Blade
#extends('layout.layout')
#section('content')
<section class="page-content">
<div class="container">
<article class="fillout-form">
<form action="{{ route('account.register.new') }}" method="post" id="registerForm">
{{ csrf_field() }}
#{{ error }}
<section v-if="step === 1">
<h1>Step One</h1>
<p>
<legend for="name">Your Name:</legend>
<input id="name" name="name" v-model="registration.name">
</p>
<p>
<legend for="surname">Your Lastname:</legend>
<input id="surname" name="surname" v-model="registration.surname">
</p>
<p>
<legend for="email">Your Email:</legend>
<input id="email" name="email" type="email" v-model="registration.email">
</p>
<p>
<legend for="number">Your Phone number:</legend>
<input id="number" name="number" type="number" v-model="registration.number">
</p>
<button #click.prevent="next()">Next</button>
</section>
<section v-if="step === 2">
<h2>Step Two</h2>
<p>
<legend for="account">Account Holder:</legend>
<input id="account" name="account" v-model="registration.account">
</p>
<p>
<legend for="iban">Your IBAN:</legend>
<input id="iban" name="iban" v-model="registration.iban">
</p>
<button #click.prevent="prev()">Previous</button>
<button #click.prevent="next()">Next</button>
</section>
<section v-if="step === 3">
<h3>Step Three</h3>
<p>
<input type="checkbox" v-model="checked">
#{{ checked ? "yes" : "no" }}
</p>
<button #click.prevent="prev()">Previous</button>
<button #click.prevent="submit()">Save</button>
</section>
</form>
</article>
</div>
</section>
<script src="https://cdn.jsdelivr.net/npm/vue/dist/vue.js"></script>
<script src="{{asset ('js/registerFlow.js')}}"></script>
#endsection
VueJS
const errors = {
empty: 'Please fill in all fields',
invalidmail: 'Your email is invalid',
};
const app = new Vue({
el:'#app',
mounted() {
window.addEventListener("keypress", function (event) {
if (event.keyCode === 13) {
event.preventDefault();
this.next();
}
})
},
data() {
return {
error: null,
step:1,
checked: false,
registration:{
name:null,
surname:null,
email:null,
number:null,
account:null,
iban:null,
},
}
},
methods: {
prev() {
this.step--;
},
next() {
this.error = "";
if(this.step === 1)
{
if(!this.registration.name || !this.registration.surname || !this.registration.email || !this.registration.number)
{
this.error = errors.empty;
return false;
}
}
if(this.step === 2)
{
if(!this.registration.account || !this.registration.iban)
{
this.error = errors.empty;
return false;
}
}
this.step++;
},
submit() {
alert('Submit to blah and show blah and etc.');
},
}
});

This is not the right way to use Vue.js and Laravel. Usually instead of writing everything in your blade you simply just create a component in your .blade file and move all the logic in your .vue file. I would suggest you read this to get an idea how to setup a simple form in Laravel/Vue

The Problem is, that you mix two templating engines. You could create a Vue component, thats not touched by blade and hand in your error data to be rendered.

Related

Is there is a way to keep my modal open in Laravel after submit and save the values to db?

I am uploading a file in Laravel 8 with having one bootstrap modal which works dynamically . everything is working fine but I want to improve my output more:
1) Update one of my forms through a modal without refreshing the page?
2) keep the modal open if the validation fails and print the errors to modal instead of my redirect page?
I will appreciate your time helping me.
my form for updating the file
<form action="{{ route('storefile' , $requisition->id) }}" method="POST"
enctype="multipart/form-data">
#csrf
#method('PUT')
<div class="form-group row">
<div class="col-sm-12">
<label for="title"> Account Status: </label>
<select class="form-control" name="acc_status">
<option value="0" {{ $requisition->acc_status == 0 ? 'selected' : '' }}> Inactive
</option>
<option value="1" {{ $requisition->acc_status == 1 ? 'selected' : '' }}> Active
</option>
</select>
</div>
<div class="col-sm-12 pt-4">
<label for="title"> Account document File: </label>
<div>
#if (!empty($requisition->acc_document))
<label class="badge-success">
{{ $requisition->acc_document }}
</label>
#else
<label class="badge-danger">
Nothing uploaded </label>
#endif
</div>
<input type="file" name="acc_document" class="form-control" id="acc_document" />
</div>
</div>
<div class="card-footer">
<div class="row">
<div class="col-md-6 text-left">
<input type="submit" value="Upload document" class="btn btn-primary">
</div>
</div>
</div>
</div>
</form>
my controller and route
public function uploadFile($id) {
$requisition = Requisition::find($id);
return view('requisition.createFile' , compact('requisition'));
}
public function storeFile(Request $request , $id) {
$request->validate([
'acc_status' => 'required',
'acc_document' => 'required|mimes:doc,docx,pdf,txt,zip|max:2000',
]);
$requisition = Requisition::find($id);
$requisition->acc_status = $request->get('acc_status');
$FileName = uniqid() .$request->file('acc_document')->getClientOriginalName();
$path = $request->file('acc_document')->storeAs('uploads', $FileName , 'public');
$requisition->acc_document = '/storage/' . $path;
}
$requisition->save();
//$requisition->update($request->all());
return back()
->with('success', 'Your file has been uploaded successfully.');
}
Route::get('upload/{id}', [RequisitionController::class, 'uploadFile'])->name('upload');
Route::put('requisition/{id}/files', [RequisitionController::class, 'storeFile'])->name('storefile');
and last part my modal and ajax in my index page to upload the file and popup will open
<div class="col-md-6">
<a style="display:inline-block; text-decoration:none; margin-right:10px;"
class="text-secondary" data-toggle="modal" id="mediumButton"
data-target="#mediumModal" title="upload"
data-attr="{{ route('upload' , $requisition->id) }}">
<i class="fas fa-upload"></i>
</a>
</div>
<script>
// display a modal (medium modal)
$(document).on('click', '#mediumButton', function(event) {
event.preventDefault();
let href = $(this).attr('data-attr');
$.ajax({
url: href,
beforeSend: function() {
$('#loader').show();
},
// return the result
success: function(result) {
// #if (count($errors) > 0) #endif
$('#mediumModal').modal("show");
$('#mediumBody').html(result).show();
$("#date-picker").datepicker({
changeMonth: true,
changeYear: true,
dateFormat: 'yy-mm-dd'
});
} ,
complete: function() {
$('#loader').hide();
},
error: function(jqXHR, testStatus, error) {
console.log(error);
alert("Page " + href + " cannot open. Error:" + error);
$('#loader').hide();
},
timeout: 8000
});
});
</script>
<!-- medium modal -->
<div class="modal fade" id="mediumModal" tabindex="-1" role="dialog" aria-labelledby="mediumModalLabel"
aria-hidden="true">
<div class="modal-dialog modal-dialog-centered modal-lg" role="document">
<div class="modal-content">
<div class="modal-body" id="mediumBody">
<form id="modal-form" method="get">
<div>
<!-- the result of displayed apply here -->
</div>
</form>
</div>
</div>
</div>
</div>
#endsection
what I want to implement looks like enter image description here
There are several ways to do this kind of thing. One way to do it, is to do something like this:
Html:
<div class="modal" id="the-modal">
<form action="{{ $theAction }}" method="POST" id="the-form">
<input type="text" name="input-name" id="the-input">
<button type="submit">
</form>
<p id="the-text"></p>
</div>
In your Controller you will return an error or an 200 response, if everything is ok.
public function theAction(Request $request , $id) {
//Do stuff
if (!$error) {
return response("OK"); //This will return a 200 response
} else {
return response("An error happened", 500); //This will return a 500 error
}
}
Then, in your JS, you'll intercept form submission and then, you're going to be able to separate errors from ok messages:
<script>
$("#the-form").on('submit', function(event) {
event.preventDefault();
let theInput = $("#the-input");
$.ajax({
url: theUrl,
data: {
the-input: theInput
}
// 200 response
success: function(result) {
$("#the-text").empty();
$("#the-text").append(result.repsonse);
} ,
error: function(jqXHR, testStatus, error) {
$("#the-text").empty();
$("#the-text").append(error.response);
}
});
});
</script>
If you want to do all this stuff inside a modal, the concept is just the same: You intercept form submission, send to controller, return separate responses for errors and 200 responses, and then update manually the inputs/texts.
I did't test the code, but the concept should work.

I am trying to build a contact form in Vue.js and Php but i am getting errors i am not quite sure how to solve this problem

I am trying to build a contact form in vue js and PHP but its not working and i am getting erros i used internet sources to build this form watched many tutorials i am not sure how to solve this. And i am very new to vuejs any kind of help would be appreciated
here's my code
<script>
export default{
data(){
return{
errorMessage: "",
successMessage: "",
errors: [],
trx_no: "",
name: "",
country: "",
email: "",
mobile_no: "",
myAddress: "",
newUser: {trx_no: "", name: "", country: "", email: "", mobile: ""}
}
},
mounted: function(){
this.getAllUsers();
},
myAddress: function() {
return this.$store.state.myAddress;
},
methods: {
saveUser: function(){
//console.log(this.newUser);
var formData = this.toFormData(this.newUser);
axios.post('http://localhost:8888/vue-and-php/public/api/update-info-form.php?action=update', formData, { crossdomain: true })
.then((response) => {
this.newUser = {trx_no: "", name: "", country: "", email: "", mobile: ""};
if(response.data.error){
this.errorMessage = response.data.message;
}else{
this.getAllUsers();
}
});
},
toFormData: function(obj){
var form_data = new FormData();
for(var key in obj){
form_data.append(key, obj[key]);
}
return form_data;
},
clearMessage: function(){
this.errorMessage = "";
this.successMessage = "";
},
//validation
checkForm: function (e) {
this.errors = [];
//if (!this.trx_no) {
// this.errors.push("TRX Address Required.");
//}
if (!this.name) {
this.errors.push("Name Required.");
}
if (!this.country) {
this.errors.push("Country Required.");
}
if (!this.email) {
this.errors.push('Email Required.');
} else if (!this.validEmail(this.email)) {
this.errors.push('Valid Email Address Required.');
}
if (!this.mobile_no) {
this.errors.push("Phone Number Required.");
}
if (!this.errors.length) {
return true;
}
e.preventDefault();
},
validEmail: function (email) {
var re = /^(([^<>()\[\]\\.,;:\s#"]+(\.[^<>()\[\]\\.,;:\s#"]+)*)|(".+"))#((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
return re.test(email);
}
}
}
</script>
and this is the contact form
<template>
<b-container>
<div class="update-info">
<div class="feature-text myinv-title">
<h5 class="title title-sm">Update your information</h5>
</div>
<form
id="app"
#submit="checkForm"
method="post"
novalidate="true"
>
<p v-if="errors.length">
<b>Please fill in all the fields</b>
<ul>
<li v-for="error in errors" class="alert alert-danger">{{ error }}</li>
</ul>
</p>
<div class="form-row">
<div class="form-group col-md-3">
<label for="trx">TRX Address No.</label>
<input
id="trx"
class="form-control trx-address-nooverflow"
v-model="myAddress"
type="text"
name="TRX Address"
readonly
>
</div>
<div class="form-group col-md-3">
<label for="name">Name</label>
<input
id="name"
class="form-control"
v-model="name"
type="text"
name="name"
>
</div>
<div class="form-group col-md-3">
<label for="name">Country</label>
<country-select
id="Country"
class="form-control"
v-model="country"
:country="country"
topCountry="US" />
</div>
<div class="form-group col-md-3">
<label for="email">Email ID</label>
<input
id="email"
class="form-control"
v-model="email"
type="email"
name="email"
>
</div>
</div>
<div class="form-row">
<div class="form-group col-md-3">
<label for="email">Mobile No</label>
<input
id="mobile"
class="form-control"
v-model="mobile_no"
type="text"
name="mobile"
>
</div>
<div class="form-group col-md-3">
<div class="top-30">
<input type="submit" value="submit" class="btn btn-btn btn-grad btn-submit" #click="saveUser();"/>
</div>
</div>
<div class="clearfix"></div>
</div>
</form>
</div>
</b-container>
</template>
Thanks in advance and #respect
NOTE: API is working fine I've tested it in Postman
I don't know what errors you get, but I see a problem with how the form is submitted.
Some changes I recommend:
The form:
<form id="app" #submit="saveUser" method="post" novalidate="true"> ... </form>
The button:
<input type="submit" class="btn btn-btn btn-grad btn-submit" />
The saveUser method:
saveUser(event){
event.preventDefault()
this.checkForm()
if(!this.errors.length) {
var formData = this.toFormData(this.newUser);
axios.post('http...')
// rest of the code
}
}
Can't test it as I don't have the project, but this should help.
However, instead of the above approach, I would recommend to do the validation at input level and let each input component deal with its own validation logic and messages. The submit button to become enabled only when no errors exist in the form. There are many component libraries for this. For the user would be much better experience to see the errors in real time than with the above way to have a list of errors upon trying to submit the form.

VueJs: How to create a select where options come from a query to other model

I'm new on VueJs and I don't know why I have the following problem:
I'm creating a view called Owners.vue where I show pub owners. In UpdateProfile.vue I show the owner data and here is where I have my problem: I'd like to build a select where the options are the possible pubs stored in my table "pubs":
My vue component is as follows:
UpdateProfile.vue
<template>
<confirm title="Edit User" ok="Save user" :show="show"
v-on:save="save"
v-on:close="close">
<div class="field">
<label class="label">Name</label>
<div class="control">
<input class="input" type="text" placeholder="User name" v-model="data.name">
</div>
</div>
<div class="field">
<label class="label">Lastname</label>
<div class="control">
<input class="input" type="text" placeholder="last name" v-model="data.lastname">
</div>
</div>
<div class="field">
<label class="label">Email</label>
<div class="control">
<input class="input" type="email" placeholder="email" v-model="data.email">
</div>
</div>
<!--Owner Pubs-->
<div class="field">
<label class="label">Pubs</label>
<div v-for="pub in data.userPubsOwned" class="control">
<input class="input" type="text" placeholder="Pub tapps" v-model="pub.name">
<div class="button is-danger" #click="deletePubFromOwner(pub.id)">
<span class="icon"><i class="far fa-trash-alt"></i></span>
<span>Delete</span>
</div>
</div>
<br>
</div>
<!--Owner Pubs-->
<!--Add Pubs to Owner-->
<div class="field">
<label class="label">Add new Pub</label>
<div class="select">
<select v-model="pubs">
<option v-for = "pub in pubs" :value="pub.id" >{{pub.name}}</option>
</select>
</div>
<br>
<br>
<div class="button is-info" #click="addPubToOwner()">
<span class="icon"><i class="fas fa-save fa-lg"></i></span>
<span>Add Tapp</span>
</div>
</div>
<!--Add Pubs to Owner-->
</confirm>
import User from "../../models/user";
export default {
props: {
show: Boolean,
data: Object,
},
data() {
return {
selected: null,
data: new User(),
pubs: [],
pub: new Pub(),
}
},
computed: {
},
methods: {
save() {
this.$emit('save', this.data);
},
close() {
this.$emit('close');
},
hasRootPermissionsAndIsNotRoot() {
return this.CONSTANTS.hasRootPermissions() && this.data.permissions !== this.CONSTANTS.ROOT_USER.permissions;
},
addPubToOwner(){
this.api.post('/owners/' + this.data.id + '/' + this.selected).then(response => {
this.data = response.data;
});
},
deletePubFromOwner(ownerpub) {
this.api.delete('/owners/' + this.data.id + '/' + ownerpub).then(response => {
this.data = response.data;
});
},
}
}
I just need to show all the pubs stored in my table pub...do I have to create a function? And how it would be?
Thanks a lot for your help!!
Yes, create a method in the mounted() section. I use a similar process to show all of the flavors/prices of a product in a shopping cart. Here is my code that you can use and hopefully extrapolate your answer from:
Mounted function to load upon vue mount
mounted: function() {
this.getPrice();
},
getPrice() function:
getPrice: function(){
axios.post('/getproductinfo', this.$data.model)
.then((response) => {
console.log(response);
this.display_name = response.data.display_name;
this.price = '$' + response.data.price;
})
.catch(error => {
this.errors.record(error.response.data.errors);
});
},
And finally the code in your view blade file
<select class="centerSelect" v-show="!loading && ordering" ref="quantitySelect" v-model="model.id" name="code_id" #change="getPrice">
#foreach ($code as $item)
<option value="{{$item->id}}">{{$item->display_name}}</option>
#endforeach
</select>

ASP.NET Core SPAServices Client Side Form Validation VUE2

I haven't been in FE solutions for a while. As a part of my FE education, I would like to create a simple VUE2 SPA app on ASP.NET Core BE using SPAServices/SPATempaltes. In general, I consider this as a great piece of technology, but I came to one problem. How to conduct client side validation. Some time ago I was using jquery validation that was integrated with ASP.NET MVC services. Can someone give me a point (maybe not the exact solution, but the places where to look for) how this can be done nowadays?
Regards
Client side Validation in VueJs or any front framework happens using HTML5 and Javascript. Like you did in Jquery all these frameworks exposes different events to subscribe and you can validate user inputs etc.
I found this post to be really helpful in doing your own validation for Vue (using vee-validation).
https://stu.ratcliffe.io/2017/7/23/integrating-vuejs-with-aspnet-core-mvc
Now it isn't using Vue as a SPA, but this is one that talks about validation. He also has a post on utilizing Vue and ASP.NET Core in a SPA here:
https://stu.ratcliffe.io/2017/07/20/vuejs-serverside-rendering-with-aspnet-core
Here is some of the validation code from the first post (in case of link rot):
(function (Vue, VeeValidate) {
if (document.querySelector('#contact')) {
Vue.use(VeeValidate);
var app = new Vue({
el: "#contact",
data: {
name: '',
email: '',
message: '',
errorMessage: ''
},
methods: {
send: function () {
this.$validator.validateAll().then(result => {
if (result) {
this.reset();
alert('Form submitted!');
} else {
this.errorMessage = 'Please fix all validation errors.'
}
});
},
reset: function () {
this.name = '';
this.email = '';
this.message = '';
this.errorMessage = '';
this.$validator.clean();
}
}
});
}
})(Vue, VeeValidate);
View
#{
ViewData["Title"] = "Contact";
}
<h2>#ViewData["Title"].</h2>
<div id="contact">
<form v-on:submit.prevent="send">
<div v-if="errorMessage.length" class="alert alert-danger">
{{ errorMessage }}
</div>
<div :class="{ 'form-group': true, 'has-error': errors.has('name'), 'has-success': name.length && !errors.has('name') }">
<label for="name">Name</label>
<input autofocus v-model="name" v-validate="'required|min:5'" class="form-control" name="name" type="text" />
<span v-show="errors.has('name')" class="text-danger">{{ errors.first('name') }}</span>
</div>
<div :class="{ 'form-group': true, 'has-danger': errors.has('email'), 'has-success': email.length && !errors.has('email') }">
<label for="email">E-mail</label>
<input v-model="email" v-validate="'required|email'" class="form-control" name="email" type="text" />
<span v-show="errors.has('email')" class="text-danger">{{ errors.first('email') }}</span>
</div>
<div :class="{ 'form-group': true, 'has-danger': errors.has('message'), 'has-success': message.length && !errors.has('message') }">
<label for="message">Message</label>
<textarea v-model="message" v-validate="'required|min:5'" class="form-control" name="message"></textarea>
<span v-show="errors.has('message')" class="text-danger">{{ errors.first('message') }}</span>
</div>
<input type="submit" value="Save" class="btn btn-primary" />
</form>
</div>
The project can be found at:
https://github.com/sturatcliffe/VueDotnetMVC

How to add and item to an Array using Vue JS?

I'm using VUE JS and for some reason I don't get the new item displayed on the view. if I use the push method, nothing happens. If I use this.$set('productos',producto) the item is displayed, but when I tried to push another item to the array, the previous item is deleted.
new Vue({
el: '#ticket',
data:{
newCodigo:{
codigo: '',
},
productos:[],
},
computed:{
errors: function(){
for(var key in this.newCodigo){
if(! this.newCodigo[key])
return true;
}
return false;
}
},
methods:{
addProducto: function(){
var codigo = this.newCodigo;
this.$http.post('/api/addProducto', codigo).success(function(producto){
this.productos.push(producto);
//this.$set('productos',producto);
});
}
}
});
I'm able to retrieve the data from the DB, but it's not displayed on the view.
<div class="container">
<div class="row">
<div id="ticket">
<form action="POST" v-on:submit.prevent="addProducto">
<input type="hidden" name="_token" id="token" value="{{ csrf_token() }}" >
<div class="form-group">
<label for="Codigo">
Escanea:
<span class="error" v-if="! newCodigo.codigo">*</span>
</label>
<input type="text" name="codigo" id="codigo" class="form-control" v-model="newCodigo.codigo">
</div>
</form>
<article v-for="producto in productos" :data="productos">
<h3>#{{producto.descripcion}}</h3>
<h3>#{{producto.precio}}</h3>
</article>
</div>
</div>
In the callback function of your ajax call, this does not point to the vm instance. Just change it to:
this.$http.post('/api/addProducto', codigo).success(function (producto) {
this.productos.push(producto);
}.bind(this));

Resources