send data to modal with laravel and vueJS - javascript

I´m traying to send data of my array data to one modal, but always in web console i can see this message:
[Vue warn]: Property or method "nombreUsuario" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property
in my component i´m creating a modal and i thinked that i could pass this data to my modal, but i can´t.
i´m traying declare one variable in export deafult of my component, but always returned me a error.
i´m showing in internet very much examples that how to do this, but i can´t.
I appreciate all help
My actual code is:
componentVUE
<template>
<div class="tabla-usuarios">
<table class="table table-hover table-striped">
<thead>
<th>Id</th>
<th>Nombre</th>
<th>Email</th>
<th>Dirección</th>
<th>Editar</th>
</thead>
<tbody>
<tr>
<td>{{ datosUsuario.id }}</td>
<td>{{ datosUsuario.nombre }}</td>
<td>{{ datosUsuario.email }}</td>
<td>{{ datosUsuario.direccion }}</td>
<td>Editar</td>
</tr>
</tbody>
</table>
<div class="modal fade" id="create">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">
<span>×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group">
<label for="nombre">Nombre:</label>
<input type="text" class="form-control" id="nombre" :nombreUsuario="nombreUsuario">
</div>
<div class="form-group">
<label for="email">Email:</label>
<input type="text" class="form-control" id="email">
</div>
<div class="form-group">
<label for="direccion">Direccion:</label>
<input type="text" class="form-control" id="direccion">
</div>
</div>
<div class="modal-footer">
<input type="submit" class="btn btn-primary" value="Guardar">
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data() {
return {
datosUsuario: [],
isOpen: false,
};
},
created: function () {
this.cargar();
},
methods: {
cargar: function () {
let url = "/getDatosPersonales";
axios
.get(url)
.then((response) => {
this.datosUsuario = response.data;
})
.catch((error) => console.error(error));
},
},
};
</script>

The easiest way to pass information to a modal is to pass it through a function and store it in a Vue property. First, in your loop, change your button to this:
<td>Editar</td>
Then you want to add both the property and the method:
<script>
export default {
data() {
return {
datosUsuario: [],
isOpen: false,
selectedItem: {}
};
},
created: function () {
this.cargar();
},
methods: {
cargar: function () {
let url = "/getDatosPersonales";
axios
.get(url)
.then((response) => {
this.datosUsuario = response.data;
})
.catch((error) => console.error(error));
},
setSelectedItem(item) {
this.selectedItem = item;
}
},
};
</script>
Then it's real easy to get that data back into your modal:
<div class="form-group">
<label for="nombre">Nombre:</label>
<input type="text" class="form-control" id="nombre" v-model="selectedItem.nombre">
</div>
You can also use the selectedItem in other functions, such as when submitting it back to the server.

Related

Close a bootstrap modal 5 after asynchronously submitting a form with vue js

I am trying to hide a modal after submitting a form. I am using bootstrap 5, vue 2 and django 3.2. I am a beginner in javascript and vue.
I can asynchronously submit the form with fetch and clear the fields, but I can't close the modal.
I report part of my code (bootstrap and vue only) which unfortunately does not provide a minimum reproducible example, but I hope it is sufficient.
The html template is:
<div style="margin-right: 230px" id="app">
<h4 style="text-align:left;float:left;">User Managment</h4>
<a
href="#"
data-bs-toggle="modal"
data-bs-target="#add_userModal"
class="btn btn-sm btn-outline-primary px-4"
style="text-align:right; float:right;">
Add
</a>
<hr style="clear:both; border-top: 1px solid grey;"/>
<table class="table" id="userTable">
<thead>
<tr>
<th class="col-md-4">First name</th>
<th class="col-md-8">Last name</th>
</tr>
</thead>
<tbody>
<tr v-for="userdb in usersdb">
<td>{% verbatim %}{{ userdb.first_name }}{% endverbatim %}</td>
<td>{% verbatim %}{{ userdb.last_name }}{% endverbatim %}</td>
</tr>
</tbody>
</table>
<div class="modal fade" id="add_userModal" tabindex="-1" aria-labelledby="add_userModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="staticBackdropLabel">Utente</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<form #submit.prevent="createUserdb">
<div class="modal-body">
<div class="form-group mb-3">
<label>First name*</label>
<input
type="text"
class="form-control"
id="first_name"
v-model="userdb.first_name"
required>
</div>
<div class="form-group mb-3">
<label>Last name*</label>
<input
type="text"
class="form-control"
id="last_name"
v-model="userdb.last_name"
required>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-sm btn-outline-secondary" data-bs-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-sm btn-outline-primary">Add</button>
</div>
</form>
</div>
</div>
</div>
</div>
The javascript code is
var app = new Vue({
el: '#app',
data: {
csrf: null,
userdb: {
first_name: '',
last_name: '',
full_name: ''},
usersdb: []
},
methods: {
async sendRequest(url, method, data) {
var myHeaders = new Headers({
'Content-Type': 'application/json',
'X-Requested-With': 'XMLHttpRequest'
})
if (method !== 'get') {
myHeaders.set('X-CSRFToken', await this.getCsrfToken())
};
var response = await fetch(url, {
method: method,
headers: myHeaders,
body: data
});
return response
},
async getCsrfToken() {
if (this.csrf === null) {
var response = await this.sendRequest(mainUrl + 'csrf', 'get')
var data = await response.json();
this.csrf = data.csrf_token;
};
return this.csrf;
},
async getUserdb() {
var response = await this.sendRequest(mainUrl, 'get');
this.usersdb = await response.json();
},
async createUserdb() {
await this.getUserdb();
await this.sendRequest(mainUrl, 'post', JSON.stringify(this.userdb));
this.userdb.first_name = '';
this.userdb.last_name = '';
await this.getUserdb();
}
},
async created() {
await this.getUserdb();
}
})
I made many attempts to add code in createUserdb, but without success. For example
document.getElementById("add_userModal").hide();
How can I hide the modal after submitting the form?
Any help is truly appreciated
You'll want to entirely manage the Bootstrap modal instance in the Vue app...
1 - First, add a new data var for the modal..
data: {
csrf: null,
userdb: {
first_name: '',
last_name: '',
full_name: ''},
usersdb: [],
myModal: null
},
2 - And a new method (ie: showModal()) to get an instance of the Bootstrap.modal and show it...
showModal(){
this.myModal = new bootstrap.Modal(document.getElementById('add_userModal'), {})
this.myModal.show()
},
3 - Bind the new method to #click handler to show the modal (instead of using data-bs attributes)...
<a
#click="showModal()"
class="btn btn-sm btn-outline-primary px-4"
style="text-align:right; float:right;">
Add
</a>
4 - Finally, call the hide() method after the async processing...
async createUserdb() {
await this.getUserdb();
await this.sendRequest(mainUrl, 'post', JSON.stringify(this.userdb));
this.userdb.first_name = '';
this.userdb.last_name = '';
this.myModal.hide()
}
Demo

Vue: login validation not working in my code

I'm creating login validation in Vue.js but the error message is not displaying and it gives me the error:
Property or method "error" is not defined on the instance but referenced during render. Make sure that this property is reactive, either in the data option, or for class-based components, by initializing the property.
Any help?
Template:
<template>
<div class="container" width="900">
<div class="row justify-content-center" style="margin-top: 10px;">
<div class="col-5">
<div v-if="error" class="alert alert-danger" role="alert">
{{error}}
</div>
<div class="card" >
<div class="card-text">
<div class="form-group" #keyup.enter="logItIn">
<input class="form-control"
v-model="login.email"
label="Email"
placeholder="Email Address"
required
> <br>
<input class="form-control"
v-model="login.password"
label="Password"
type="password"
placeholder="Password"
required>
</div>
</div>
<button type="button" class="btn btn-secondary" #click='logItIn'>Login</button>
</div>
</div>
</div>
</div>
</template>
Script:
import axios from 'axios'
export default {
data() {
return {
login: {
email:"",
password:"",
error: ""
}
}
},
methods: {
async logItIn() {
try {
axios.post('https://odevin-api.herokuapp.com/login',this.login)
.then(response => {
console.log(response)
let newToken=response.data.response.token;
window.token=newToken;
let user=response.data.response.user; //response
localStorage.setItem('token',newToken);
localStorage.setItem('user',JSON.stringify(user));
window.axios.defaults.params={api_token:newToken}
// Event.$emit('login',user);
this.$router.push('/');
});
} catch(e) {
this.error = 'invalid user name or password';
}
}
}
}
you referenced {{ error }} in your template but in your data object, error is a property of login object. so vue can't find it properly.
either change the usage in your template to {{ login.error }} or define it in your data object like this:
data() {
return {
error: '',
login: {
email: '',
password: '',
},
}
}

Laravel (vue and vuex) Adding data always return unautherized

I'm currently making a website that applies Laravel that handles backend, Vuejs that handles frontend and Vuex that handles the CRUD Axios. For my authentication, I didn't use the default that laravel provides instead i use the laravel passport.
I was trying to add data on mysql database but sadly i always receive this error.
message Unauthenticated.
I don't know how to fix the error or pinpoint the root of an error.
Codes
cycle.js (Vuex)
const actions = {
addCycle(context, cycle){
axios.post('/cycle',{
date_loading: cycle.date_loading,
chicken_population: cycle.chicken_population,
clean_up: cycle.clean_up,
date_harvest: cycle.date_harvest,
date_manure_collection: cycle.date_manure_collection,
date_cleaning: cycle.date_cleaning,
date_disinfection: cycle.date_disinfection,
date_rest: cycle.date_rest,
date_next_loading: cycle.date_next_loading,
})
.then(response =>{
context.commit('addCycle',response.data)
})
.catch(error =>{
console.log(error)
})
},
}
ModalAddCycle.vue
<template>
<div
class="modal fade"
id="modalAddCycle"
tabindex="-1"
role="dialog"
aria-labelledby="modalTitle"
aria-hidden="true"
>
<div class="modal-dialog modal-dialog-centered" role="document">
<div class="modal-content">
<ValidationObserver v-slot="{ invalid, passes, validate }">
<form #submit.prevent="passes(createCycle)">
<div class="modal-header">
<h5 class="modal-title" id="modalTitle">Add Cycle</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span class="color-close" aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<div class="form-group pl-2 pr-2">
<ValidationProvider
name="loading date"
mode="eager"
v-slot="{ classes, errors }"
>
<label for="date_loading">Loading Date</label>
<div class="row">
<div class="col-9">
<v-date-picker
:class="classes"
v-model="date_loading"
id="date_loading"
title-position="left"
required
/>
</div>
<div class="col ml-4">
<!-- <button class="btn btn-primary" type="button" #click="validate">Check</button> -->
</div>
</div>
<small class="form-text text-error">{{ errors[0] }}</small>
</ValidationProvider>
</div>
<div class="form-group pl-2 pr-2">
<ValidationProvider
name="chicken population"
mode="eager"
rules="numeric"
v-slot="{ classes, errors }"
>
<label for="chicken_population">Chicken Population</label>
<input
:class="classes"
v-model="chicken_population"
id="chicken_population"
type="textr"
class="form-input"
required
/>
<small class="form-text text-error">{{ errors[0] }}</small>
</ValidationProvider>
</div>
<div class="form-group pl-2 pr-2">
<ValidationProvider
name="clean up"
rules="numeric"
mode="eager"
v-slot="{ classes, errors }"
>
<label for="clean_up">Clean up</label>
<input
:class="classes"
v-model="clean_up"
id="clean_up"
type="text"
class="form-input"
required
/>
<small class="form-text text-error">{{ errors[0] }}</small>
</ValidationProvider>
</div>
<div class="form-group pl-2 pr-2">
<label for="date_harvest">Harvest Date</label>
<input
:value="dateHarvest"
id="date_harvest"
readonly
class="form-control-plaintext ml-2"
/>
</div>
<div class="form-group pl-2 pr-2">
<label for="date_manure_collection">Manure Collection Date</label>
<input
:value="dateManureCollection"
id="date_manure_collection"
readonly
class="form-control-plaintext ml-2"
/>
</div>
<div class="form-group pl-2 pr-2">
<label for="date_cleaning">Cleaning Date</label>
<input
:value="dateCleaning"
id="date_cleaning"
readonly
class="form-control-plaintext ml-2"
/>
</div>
<div class="form-group pl-2 pr-2">
<label for="date_disinfection">Disinfection Date</label>
<input
:value="dateDisinfection"
id="date_disinfection"
readonly
class="form-control-plaintext ml-2"
/>
</div>
<div class="form-group pl-2 pr-2">
<label for="date_rest">Rest Date</label>
<input
:value="dateRest"
id="date_disinfection"
readonly
class="form-control-plaintext ml-2"
/>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-dismiss="modal">Cancel</button>
<button type="submit" class="btn btn-success">Create</button>
</div>
</form>
</ValidationObserver>
</div>
</div>
</div>
</template>
<script>
import { mapActions } from "vuex";
name: "modalAddCycle";
export default {
data() {
return {
date_loading: new Date(),
chicken_population: "",
clean_up: "",
date_harvest: "",
date_manure_collection: "",
date_cleaning: "",
date_disinfection: "",
date_rest: ""
};
},
methods: {
...mapActions(["addCycle"]),
createCycle() {
this.addCycle({
date_loading: moment(this.date_loading).format("YYYY-MM-DD"),
chicken_population: this.chicken_population,
clean_up: this.clean_up,
date_harvest: moment(this.date_loading).format("YYYY-MM-DD"),
date_manure_collection: moment(this.date_loading).format("YYYY-MM-DD"),
date_cleaning: moment(this.date_loading).format("YYYY-MM-DD"),
date_disinfection: moment(this.date_loading).format("YYYY-MM-DD"),
date_rest: moment(this.date_loading).format("YYYY-MM-DD")
})
.then(response => {
toast.fire({
type: "success",
title: "Create cycle successfully!"
});
console.log()
$("#modalAddCycle").modal("hide");
})
.catch(error => {
swal.fire({
type: "error",
title: "There was something wrong!",
text: error.response.data.message,
showConfirmButton: false,
timer: 3000
});
});
}
},
computed: {
dateHarvest() {
this.date_harvest = moment(this.date_loading)
.add(this.clean_up, "days").format("MM/DD/YYYY");
return this.date_harvest;
},
dateManureCollection() {
this.date_manure_collection = moment(this.date_harvest)
.add(2, "days").format("MM/DD/YYYY")
return this.date_manure_collection;
},
dateCleaning() {
this.date_cleaning = moment(this.date_harvest)
.add(9, "days").format("MM/DD/YYYY")
return this.date_cleaning;
},
dateDisinfection() {
this.date_disinfection = moment(this.date_harvest)
.add(10, "days").format("MM/DD/YYYY")
return this.date_disinfection;
},
dateRest() {
this.date_rest = moment(this.date_harvest)
.add(20, "days").format("MM/DD/YYYY")
return this.date_rest;
}
}
};
</script>
CycleController.php
public function __construct()
{
$this->middleware('auth:api');
}
/**
* Display a listing of the resource.
*
* #return \Illuminate\Http\Response
*/
public function index()
{
}
public function store(Request $request)
{
// VALIDATION
$this->validate($request, array(
'date_loading' => 'required|date',
'clean_up' => 'required|numeric',
'chicken_population' => 'required|numeric',
));
// STORING CYCLE DATA
$storeCycle = Cycle::create([
'date_loading' => request('date_loading'),
'clean_up' => request('clean_up'),
'chicken_population' => request('chicken_population'),
'date_harvest' => request('date_harvest'),
'date_manure_collection' => request('date_manure_collection'),
'date_cleaning' => request('date_cleaning'),
'date_disinfection' => request('date_disinfection'),
'date_rest' => request('date_rest'),
'date_next_loading' => request('date_next_loading'),
'user_id' => Auth::id()
]);
// GETTING THE CYCLE ID
$cycle = Cycle::where([
['date_loading',$request->get('date_loading')],
['date_harvest',$request->get('date_harvest')],
['user_id' => Auth::id()],
])->first();
//CHECKS IF CYCLE DATA WAS EXISTED
if($cycle){
//STORING CHICKEN POPULATION IN POPULATION TABLE
Population::create([
'chicken_population'=> request('chicken_population'),
'chicken_available'=> request('chicken_population'),
'cycle_id' => $cycle->id ?? 0,
'user_id' => Auth::id()
]);
}
return $storeCycle;
}
api.php
Route::middleware('auth:api')->get('/user', function (Request $request) {
return $request->user();
});
Route::apiResources(['cycle' => 'API\CycleController']);
web.php
Route::get('/{any?}', function (){
return view('layout');
})->where('any', '^(?!api\/)[\/\w\.-]*');
You need a passport token for javascript authentication and I quote: All you need to do is add the CreateFreshApiToken middleware to your web middleware group in your app/Http/Kernel.php file:
'web' => [
// Other middleware...
\Laravel\Passport\Http\Middleware\CreateFreshApiToken::class,
],
For more details check the Laravel documentation from here
Note: Make sure the User model uses Laravel\Passport\HasApiTokens trait
Not sure if your problem is the same but there is a PR in the laravel repo regarding a similar error with API authentication that may help.
https://github.com/laravel/laravel/pull/4764
The original issue and explanation is listed in the description but here's a summary:
OK, I've looked into this and I'm pretty sure it has nothing to do with JSON or the handling of the AuthenticationException, because the AuthenticationException is never even thrown. Try dumping $request->expectsJson() - does this return true? It probably does.
This line is indeed the problem. It's called when the parent tries to construct the Exception:
throw new AuthenticationException(
'Unauthenticated.', $guards, $this->redirectTo($request)
);
But the login route doesn't exist by default, so the route('login') throws an InvalidArgumentException.
This bug is present even in a fresh Laravel install:
laravel new auth-test
cd auth-test
php artisan serve
and then
curl -H "Accept: application/json" http://localhost:8000/api/user
and you will see the same Exception.
This bug seems to have been introduced in laravel/laravel#a14e623.
Workaround: Add a route named "login" or remove the call to route('login') from the Middleware.

how to set value form input vue js from json

please have a problem here. I want to display the value from the input form: name and position. but the data is in the form of json.
{"id":5,"name":"the name","pos":"the position"}
This is template html vue js
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
Edit <b>{{name}}</b>
</div>
<div class="card-body">
<form #submit="edit()" method="post" onclick="return false">
<div class="form-group">
<label for="">Name</label>
<input v-model="input.nameInput" type="text" value="?" autocomplete="off" class="form-control">
</div>
<div class="form-group">
<label for="">Position</label>
<input v-model="input.posInput" value="?" type="text" autocomplete="off" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Edit</button>
</form>
</div>
</div>
</div>
</div>
</div>
</template>
And this is java script of template file vue js
<script>
export default {
data(){
return{
name:'',
pos:'',
input:{
nameInput:'',
posInput:''
}
}
},
methods:{
getEmploye(){
axios.get('/employes_api/'+this.$route.params.id).then(response => {
this.name = response.data.name;
this.pos = response.data.pos;
});
},
edit(){
axios.put('/employes_api/'+this.$route.params.id, {
name: this.name,
pos: this.position,
}).then(response => {
this.$route.employe;
});
}
},
mounted(){
this.getEmploye();
}
}
</script>
Thanks for your help.
As described in your question, if the data received is
{"id":5,"name":"the name","pos":"the position"}
then you getEmploye method should be :
getEmploye(){
axios.get('/employes_api/'+this.$route.params.id).then(response => {
this.name = response.name;
this.pos = response.pos;
});
On element’s value, you may use the following to display data you have received from the api:
value=“{{name}}”
That means you are getting the value from name data.
Also, to test if that works, you may assign first a dummy data/value to name.
You don't need to make two separate variables one for the inputs and the other for the display, just keep the same variable for both, it will be automatically updated on the display and in the inputs while the user is typing, that's the beauty of Vue.
So instead of
data(){
return{
name:'',
pos:'',
input:{
nameInput:'',
posInput:''
}
}
},
Just keep
data(){
return{
name:'',
pos:''
}
},
For the template inputs use :
<input v-model="name" type="text" autocomplete="off" class="form-control">
...
<input v-model="pos" type="text" autocomplete="off" class="form-control">
The overall result should look like this :
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card">
<div class="card-header">
Edit <b>{{name}}</b>
</div>
<div class="card-body">
<form #submit="edit()" method="post">
<div class="form-group">
<label for="">Name</label>
<input v-model="name" type="text" autocomplete="off" class="form-control">
</div>
<div class="form-group">
<label for="">Position</label>
<input v-model="position" type="text" autocomplete="off" class="form-control">
</div>
<button type="submit" class="btn btn-primary">Edit</button>
</form>
</div>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data(){
return{
name:'',
pos:''
}
},
methods:{
getEmploye(){
axios.get('/employes_api/'+this.$route.params.id).then(response => {
this.name = response.data.name;
this.pos = response.data.pos;
});
},
edit(){
axios.put('/employes_api/'+this.$route.params.id, {
name: this.name,
pos: this.pos,
}).then(response => {
this.$route.employe;
});
}
},
created(){
this.getEmploye();
}
}
Ps : Didn't test the code, if there is any error just let me know
Use :value=“name”, e.g <input :value="name"/>.

Can't get error handing in vue.js 1.0 and Laravel 5.1 to work

I'm building an app which uses vue.js and Laravel 5 to persist data into a database. So far, it can successfully save data.
My problem
I'm having trouble with displaying errors when the user validation fails using the 'out of the box' authorisation that Laravel has. I keep getting the error:
[Vue warn]: Error when evaluating expression "form.errors.length > 0"
(referring to errors.js in my code below)
Piecing it together
So how this should work...a user enters their details into the registration page and Vue (using vue-resource) makes an AJAX request to the 'out of the box' Laravel AuthController#postRegister method. On error, Laravel nicely spits out the JSON error messages we all expect. Now in theory, the sendRegistration method within my subscription.js file should detect the errors that Laravel spits out (I've tested this with console.log's and it works) and pass them into the errors.js component to display the errors within the <spark-errors> tags. In order to do this, it uses a setErrorsOnForm: function within my <head> tag. However it's not working as expected and I cannot workout why.
My code
My code consists of a registration page:
<!DOCTYPE html>
<html lang="en">
<head>
<!-- Laravel Spark Globals -->
<script>
window.Spark = {
// Laravel CSRF Token
csrfToken: '{{ csrf_token() }}',
// Flatten errors and set them on the given form
setErrorsOnForm: function (form, errors) {
if (typeof errors === 'object') {
form.errors = _.flatten(_.toArray(errors));
} else {
form.errors.push('Something went wrong. Please try again.');
}
}
}
</script>
</head>
<body>
<div id="spark-app">
<spark-subscription-register-screen inline-template>
<div class="panel panel-default">
<div class="panel-heading">Your Information</div>
<div class="panel-body">
<spark-errors form="#'{'{ registerForm '}'}"></spark-errors>
<form class="form-horizontal" role="form" id="subscription-basics-form">
<div class="form-group">
<label class="col-md-4 control-label">Your Name</label>
<div class="col-md-6">
<input type="text" class="form-control spark-first-field" name="name" v-model="registerForm.name">
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label">E-Mail Address</label>
<div class="col-md-6">
<input type="email" class="form-control" name="email" v-model="registerForm.email">
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label">Password</label>
<div class="col-md-6">
<input type="password" class="form-control" name="password" v-model="registerForm.password">
</div>
</div>
<div class="form-group">
<label class="col-md-4 control-label">Confirm Password</label>
<div class="col-md-6">
<input type="password" class="form-control" name="password_confirmation" v-model="registerForm.password_confirmation">
</div>
</div>
<div v-if="freePlanIsSelected">
<div class="form-group">
<div class="col-sm-6 col-sm-offset-4">
<div class="checkbox">
<label>
<input type="checkbox" v-model="registerForm.terms"> I Accept The Terms Of Service
</label>
</div>
</div>
</div>
<div class="form-group">
<div class="col-sm-6 col-sm-offset-4">
<button type="submit" class="btn btn-primary" v-on:click="register" :disabled="registerForm.registering">
<span v-if="registerForm.registering">
<i class="fa fa-btn fa-spinner fa-spin"></i> Registering
</span>
<span v-if=" ! registerForm.registering">
<i class="fa fa-btn fa-check-circle"></i> Register
</span>
</button>
</div>
</div>
</div>
</form>
</div>
</div>
</spark-subscription-register-screen inline-template>
</div>
</body>
</html>
From a vue.js perspective there is a subscription.js file:
Vue.component('spark-subscription-register-screen', {
/*
* Initial state of the component's data.
*/
data: function () {
return {
registerForm: {
nhs_org: '', team_name: '', name: '', email: '', password: '', password_confirmation: '',
plan: '', terms: false, coupon: null, invitation: null,
stripe_token: null, errors: [], registering: false
},
};
},
methods: {
/*
* Initialize the registration process.
*/
register: function(e) {
var self = this;
e.preventDefault();
this.registerForm.errors = [];
this.registerForm.registering = true;
return this.sendRegistration();
},
/*
* After obtaining the Stripe token, send the registration to Spark.
*/
sendRegistration: function() {
this.$http.post('/register', this.registerForm)
.success(function(response) {
window.location = '/';
})
.error(function(errors) {
this.registerForm.registering = false;
Spark.setErrorsOnForm(this.registerForm, errors);
});
},
}
});
and there is an errors.js Vue component:
/*
* Common Error Display Component.
*/
Vue.component('spark-errors', {
props: ['form'],
template: "<div><div class='alert alert-danger' v-if='form.errors.length > 0'>\
<strong>Whoops!</strong> There were some problems with your input.<br><br>\
<ul>\
<li v-for='error in form.errors'>\
{{ error }}\
</li>\
</ul>\
</div></div>"
});
Now the Vue files which piece all of this together (in the correct order):
app.js:
require('./core/dependencies');
if ($('#spark-app').length > 0) {
new Vue(require('./core/spark.js'));
}
core/dependencies.js:
/*
* Load Vue & Vue-Resource.
*
*/
if (window.Vue === undefined) window.Vue = require('vue');
require('vue-resource');
Vue.http.headers.common['X-CSRF-TOKEN'] = Spark.csrfToken;
/*
* Load Underscore.js, used for map / reduce on arrays.
*/
if (window._ === undefined) window._ = require('underscore');
/*
* Load jQuery and Bootstrap jQuery, used for front-end interaction.
*/
if (window.$ === undefined || window.jQuery === undefined) window.$ = window.jQuery = require('jquery');
require('bootstrap-sass/assets/javascripts/bootstrap');
core/spark.js:
/*
* Load the Spark components.
*/
require('./components');
/**
* Export the Spark application.
*/
module.exports = {
el: '#spark-app',
/*
* Bootstrap the application. Load the initial data.
*/
ready: function () {
$(function() {
$('.spark-first-field').filter(':visible:first').focus();
});
}
}
and core/components.js:
require('./../auth/registration/subscription');
require('./../common/errors');
I had the same issue, and instead of using the out of the box errors from spark, I defined my own component:
<template>
<div v-if="errors">
<div class="alert alert-danger" v-if="formattedErrors.length > 0">
<strong>Whoops!</strong> There were some problems with your input.<br><br>
<ul>
<li v-for="error in formattedErrors">
{{ error }}
</li>
</ul>
</div>
</div>
</template>
<script>
export default {
props: ['errors'],
computed: {
formattedErrors() {
return this.format(this.errors);
}
},
methods: {
format(errors) {
if (typeof errors === 'undefined') {
return [];
}
if (typeof errors === 'object') {
return _.flatten(_.toArray(errors));
}
}
}
}
</script>
Then you bind in your html:
<form-errors :errors="registerForm.errors"></form-errors>
It makes sense because your component just need the to now about errors, and nothing else about the registerForm.
Hope this helps.

Categories

Resources