Having a strange issue, when using x-for to loop through an array i am getting an additional blank set of form elements. If i take out all of the code between the templates and just replace with a h1 with x-text as event.name - i only get the 2 iterations.
Puling my hair out, any ideas why this might be occuring? Here is the code.
Appreciate your assistance.
I have confirmed that the array being passed in only has 2 entries.
<div x-data="updateEvent()">
<template x-for="event in events">
<form action="test10" #submit.prevent="submitData">
<div class="grid grid-cols-4 gap 4 flex">
<div>
</div>
<div class="flex items-center content-center justify-center py-5">
<img class="w-full rounded" :src="imagePath + event.image" alt="" />
</div>
<div>
<div class="pl-4 my-10">
<div>
<x-label for="name" :value="__('Name')" class="mb-2" />
<x-input id="name" class="block mt-1 w-full" type="text" name="name"
::value="" x-model="event.name" x-bind:disabled="!disabled" required
autofocus />
</div>
<div>
<x-label for="date" :value="__('Date')" />
<x-input id="date" class="block mt-1 w-full" type="text" name="date"
::value="" x-model="event.date" required autofocus />
</div>
<div>
<x-label for="statsLink" :value="__('Stats Link')" />
<x-input id="statsLink" class="block mt-1 w-full" type="text"
name="statsLink" ::value="" x-model="event.statsLink" required
autofocus />
</div>
<div>
<x-label for="frontLink" :value="__('Front Link')" />
<x-input id="frontLink" class="block mt-1 w-full" type="text"
name="frontLink" ::value="" x-model="event.frontLink" required
autofocus />
</div>
</div>
</div>
<div class="flex items-center content-center justify-center ">
<x-button class="ml-3" x-on:click="disabled = !disabled, save = !save">
Edit Event
</x-button>
<br />
<x-button class="ml-3" x-bind:disabled="!disabled">
Update Event
</x-button>
</div>
</div>
</form>
</template>
</div>
I have tried cutting down the code to H1 and then it seems to iterate correctly - only twice.
Adding in the updateEvent() code for reference.
`<script>
function updateEvent() {
return {
events: [{
id: 1,
name: 'Event Name 1',
date: '2023-02-11 00:00:00',
image: '/eventCoverImages/EventCoverImage1.jpg',
cards: null
},
{
id: 2,
name: 'Event Name 2',
date: '2023-01-14 00:00:00',
image: '/eventCoverImages/EventCoverImage2.jpg',
cards: null
}
],
show: true,
disabled: false,
save: true,
imagePath: "{{ asset('app') . '/' }}",
}
}
`
Related
I've created an Laravel Vue SPA app. Right now, I can successfully retrieved the data in object format and can display the names in vue-multiselect (https://vue-multiselect.js.org/) when selected. Also, I can already save the selected options to the database in an object format. My question is how can I save only the id's in an array?
This is the results from api:
[
{
"id": 1,
"name": "Shoe Machine Operators",
"description": "Iusto cupiditate quo veniam.",
"created_at": "2022-03-23T10:23:35.000000Z",
"updated_at": "2022-03-23T10:23:35.000000Z"
},
{
"id": 2,
"name": "Librarian",
"description": "Vero eius quidem quo fugiat.",
"created_at": "2022-03-23T10:23:35.000000Z",
"updated_at": "2022-03-23T10:23:35.000000Z"
}
]
Here's my markup code where my vue-multiselect element is:
<form #submit.prevent="addEmployee">
<div class="flex space-x-6 md:w-3/4">
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2" for="name">First Name</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline required" name="name" id="name" type="text" placeholder="First Name" tabindex="1" v-model="employee.first_name" />
</div>
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2" for="name">Last Name</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline required" name="name" id="name" type="text" placeholder="Last Name" tabindex="2" v-model="employee.last_name" />
</div>
</div>
<div class="flex space-x-6 md:w-3/4">
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2" for="designation_id">Designation</label>
<multiselect v-model="employee.designation_id"
:options="designation_options"
:multiple="true"
:close-on-select="false"
:clear-on-select="false"
:preserve-search="true"
placeholder="Pick one or many"
label="name"
track-by="name"
:preselect-first="true"
>
<template slot="selection" slot-scope="{ values, search, isOpen }"><span class="multiselect__single" v-if="values.length && !isOpen">{{ values.length }} options selected</span></template>
</multiselect>
<pre class="language-json"><code>{{ employee.designation_id }}</code></pre>
</div>
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2" for="position_id">Position</label>
<multiselect v-model="employee.position_id"
:options="position_options"
:multiple="true"
:close-on-select="false"
:clear-on-select="false"
:preserve-search="true"
placeholder="Pick one or many"
label="name"
track-by="name"
:preselect-first="true"
>
<template slot="selection" slot-scope="{ values, search, isOpen }"><span class="multiselect__single" v-if="values.length && !isOpen">{{ values.length }} options selected</span></template>
</multiselect>
<pre class="language-json"><code>{{ employee.position_id }}</code></pre>
</div>
</div>
<div class="flex space-x-6 md:w-3/4">
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2" for="basic_pay">Basic Pay</label>
<div class="relative rounded">
<div class="absolute inset-y-0 left-0 pl-3 flex items-center pointer-events-none">
<span class="text-gray-700">₱</span>
</div>
<input class="shadow appearance-none border rounded w-full py-2 pl-8 pr-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline required" name="basic_pay" id="basic_pay" type="number" step="any" placeholder="00.00" tabindex="5" v-model="employee.basic_pay" />
<div class="absolute inset-y-0 right-0 flex items-center"><label for="basic_pay" class="sr-only">Basic Pay</label>
</div>
</div>
</div>
<div class="md:w-3/6 mb-4 flex-1"> </div>
</div>
<button type="submit" class="sm:hidden md:flex bg-blue-500 hover:bg-blue-400 text-white font-bold py-2 px-4 border-b-4 border-blue-700 hover:border-blue-500 rounded outline-none focus:outline-none">Create</button>
</form>
Here's my script:
<script>
export default {
data() {
return {
employee: {},
designation_id: [],
designation_options: [],
}
},
methods: {
addEmployee() {
this.axios.post('/api/employees', this.employee).then(response => (this.$router.push({
name: 'employees'
}))).catch(err => console.log(err)).finally(() => this.loading = false)
},
getDesignationNames() {
this.axios.get('/api/designation').then((res) => {
this.designation_options = res.data;
}).catch(err => console.log(err))
},
},
created: function() {
this.getDesignationNames();
},
}
</script>
Any help is much appreciated.
I tried getting only the id using .map() function but it caused the vue-multiselect to not show the names and return only the first clicked result in an id format.
getDesignationNames() {
this.axios.get('/api/designation').then((res) => {
this.designation_options = res.data.map((a) => {
return a.id;
});
}).catch(err => console.log(err))
},
Use v-model.
Define v-model binding as an array.
Check this example
<script setup>
import { ref } from 'vue'
const data = ref([{id:1,name:"first"},{id:2,name:"second"},{id:3,name:"third"},{id:4,name:"forth"},{id:5,name:"fifth"}])
const selected = ref(["2","4"])
</script>
<template>
<select v-model="selected" multiple>
<option v-for="item in data" :value="item.id">{{item.name}}</option>
</select>
<div>Selected: {{selected}}</div>
</template>
this is the variable that holds the form data
userForm: new Form({
last_name: '',
first_name: '',
other_name: '',
email: '',
dob: '',
gender: '',
phone_number: '',
}),
on click of the edit button, i use the row id to fetch the data from backend and am using vform method fill to fill the userForm variable with the response data
'click .edit': function (e, value, row){
axios
.get('/data/admin/'+row.id)
.then(response => {
this.loading = false;
//let data = response;
this.userForm.fill(response.data);
$('#adminEditModal').modal('show');
}).catch(error => {
this.loading = false;
this.error = error.response.data.message || error.message;
});
},
this is my form
<form #submit.prevent="UpdateUser" ref="userForm">
<div class="modal-body">
<div class="login-logo">
<img src="" width="100" height="auto" alt="user">
</div>
<div class="form-group">
<label>Last Name</label>
<input v-model="userForm.last_name" type="text" name="last_name"
class="form-control" :class="{ 'is-invalid': userForm.errors.has('last_name') }">
<has-error :form="userForm" field="last_name"></has-error>
</div>
<div class="form-group">
<label>Firat Name</label>
<input v-model="userForm.first_name" type="text" name="first_name"
class="form-control" :class="{ 'is-invalid': userForm.errors.has('first_name') }">
<has-error :form="userForm" field="first_name"></has-error>
</div>
<div class="form-group">
<label>Other Name</label>
<input v-model="userForm.other_name" type="text" name="other_name"
class="form-control" :class="{ 'is-invalid': userForm.errors.has('other_name') }">
<has-error :form="userForm" field="other_name"></has-error>
</div>
<div class="form-group">
<label>Email</label>
<input v-model="userForm.email" type="email" name="email"
class="form-control" :class="{ 'is-invalid': userForm.errors.has('email') }">
<has-error :form="userForm" field="email"></has-error>
</div>
<div class="form-group">
<label>Date Of Birth</label>
<input v-model="userForm.dob" type="date" name="dob"
class="form-control" :class="{ 'is-invalid': userForm.errors.has('dob') }">
<has-error :form="userForm" field="dob"></has-error>
</div>
<div class="form-group">
<label>Gender</label>
<select v-model="userForm.gender" type="text" name="gender"
class="form-control" :class="{ 'is-invalid': userForm.errors.has('gender') }" >
<option>Male</option>
<option>Female</option>
</select>
<has-error :form="userForm" field="gender"></has-error>
</div>
<div class="form-group">
<label>Phone Number</label>
<input v-model="userForm.phone_number" type="text" name="phone_number"
class="form-control" :class="{ 'is-invalid': userForm.errors.has('phone_number') }">
<has-error :form="userForm" field="phone_number"></has-error>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-danger" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-success">Update <i class="fas fa-upload"></i></button>
</div>
</form>
I'm doing a web application, and I get to a point where I can not move forward, I do not know how to do this, I'm starting with laravel so maybe the solution is very simple:
public function detalle($id){
// $nota = App\Nota::find($id);
//Aquí valida si existe sino redirije al 404
$producto = App\Producto::findOrFail($id);
$cantidad = 1;
return view('productos.detalle', compact('producto','cantidad'));
}
View:
<div class="card col-6 ">
<div class="card-body card-buy">
<h1 class="display-4 ">{{$producto->nombre}}</h1>
<p class="h3 mt-5">S/ {{$producto->precio}}</p>
<div class="form-inline">
<i class="fas fa-credit-card h1 mr-1"></i>
<p class="mt-2 "> <b>Metodo de pago:</b> A convenir</p>
</div>
<div class="form-inline">
<i class="fab fa-mailchimp ml-2 mr-2 h1"></i>
<p class="mt-2 "> <b>Envio:</b> Disponible a todo el pais</p>
</div>
<div class="form-inline ">
<div class="mt-n5 mr-2">
<b>Cantidad:</b>
</div>
<div class="def-number-input number-input safari_only">
<button onclick="this.parentNode.querySelector('input[type=number]').stepDown()" class="minus"></button>
<input readonly="readonly" class="quantity" min="1" max="{{$producto->stock}}" name="quantity" value="{{$cantidad}}" type="number">
<button onclick="this.parentNode.querySelector('input[type=number]').stepUp()" class="plus"></button>
</div>
<div class="mt-n5 ml-2">
<b class="text-decoration-none"> ( {{$producto->stock}} disponibles)</b>
</div>
</div>
Comprar
</div>
</div>
https://gyazo.com/febcd4c38cb3ef244e7424a3d92079a4
I already created the detail view of my product, and I put a button for the user to select the amount of products he wants, until there is everything right ...
But I want that number that the person chose to go to the next view, which is to confirm
https://gyazo.com/f56cf578808e75a0fab25eeffa8d2c5d
but that data {{$cantidad}} I do not know how to pass it to this new view I put the code:
Controller:
public function detallescompra($id){
$producto = App\Producto::findOrFail($id);
$total = 0;
$num1 = $producto->precio;
$num2 = $producto->stock;
$total = $num1 * $num2;
return view('productos.compra', compact('producto','total'));
}
and in the view:
<div class="container">
<div class="row" id="contenido">
<div class="col-md-8">
<div class="card">
<div class="card-header d-flex justify-content-between align-items-center">
<span>Revisa y Confirma</span>
Seguir viendo...
</div>
<div class="card-body">
#if ( session('mensaje') )
<div class="alert alert-success">{{ session('mensaje') }}</div>
#endif
<form method="POST" action="{{ route ('productos.comprafinal') }}">
#csrf
<label class="text-gray">Contacto y Envio:</label>
<div id="contenido">
<input type="name" name="usuario" placeholder="Nombre y Apellido" class="form-control mb-2" required />
<input type="email" name="email" placeholder="Email de contacto" class="form-control mb-2" required />
<input type="number" name="tlf" placeholder="Numero de telefono" class="form-control mb-2" />
<input type="street-address" name="direccion" placeholder="Direccion (Calle - #Casa - Referencia)" class="form-control mb-2" validate required />
<input type="text" name="id" placeholder="" class="form-control mb-2 d-none" value="{{$producto->id}}" />
<input type="text" name="timestamps" placeholder="" class="form-control mb-2 d-none" value="{{$producto->timestamp}}" />
<label class="text-gray">Producto:</label>
<input type="text" name="nombre" placeholder="Precio del Producto" class="form-control mb-2" value="{{$producto->nombre}}" readonly="readonly" />
<input type="text" name="precio" placeholder="Precio del Producto" class="form-control mb-2" value="Precio por unidad: S/ {{$producto->precio}}" readonly="readonly" id="valor1" />
<input type="text" name="cantidad" placeholder="Precio del Producto" class="form-control mb-2" value="Numero de productos: " readonly="readonly" id="valor2" />
<input type="text" name="" placeholder="Precio del Producto" class="form-control mb-2" value="Total a pagar: S/ {{$total}}" readonly="readonly" id="total" />
<button class="btn btn-success btn-block" type="submit">Comprar</button>
</div>
</form>
</div>
</div>
</div>
<div class="col-mod-4">
<div class="card" style="width: 18rem;">
<img src="{{$producto->img}}" class="card-img-top" alt="...">
</div>
</div>
</div>
I just need to spend that {{$cantidad}} in my view productos.compra, So far I have tried many things but nothing has given me even the minimum result
I'm new to this, I need help :(
GG :D
public function detallescompra(Request $request,$id){
$producto = App\Producto::findOrFail($id);
$cantidad = $request->input('cantidad');
$total = 0;
$num1 = $producto->precio;
$num2 = $cantidad;
$total = $num1 * $num2;
return view('productos.compra', compact('producto','total','cantidad'));
}
View:
<form action="{{ route('productos.compra-confirm', $producto) }}" method="POST">
#csrf
<div class="form-inline ">
<div class="mt-n5 mr-2">
<b>Cantidad:</b>
</div>
<div class="def-number-input number-input safari_only">
<button type="button" onclick="this.parentNode.querySelector('input[type=number]').stepDown()" class="minus"></button>
<input readonly="readonly" class="quantity" min="1" max="{{$producto->stock}}" name="cantidad" value="{{$cantidad}}" type="number">
<button type="button" onclick="this.parentNode.querySelector('input[type=number]').stepUp()" class="plus"></button>
</div>
<div class="mt-n5 ml-2">
<b class="text-decoration-none"> ( {{$producto->stock}} disponibles)</b>
</div>
</div>
<button type="submit" class=" align-bottom btn btn-success btn-lg btn-block ">Comprar</button>
</div>
</div>
</form>
routes web:
Route::post('/comprar/{id}', 'HomeController#detallescompra')->name('productos.compra-confirm');
User have to register through two steps. both steps have modal to fill details. for that i have two component ComponentA for first modal and componentB for second modal. Iwant to close first modal on axios success response and open second modal for second registration step.
<template>
<!--sction user-signup 1-->
<div class="signup">
<div class="modal" id="user-signup-1">
<div class="modal-dialog">
<div class="modal-content">
<button type="button" class="close" data-dismiss="modal">×</button>
<!-- Modal body -->
<div class="modal-body text-center" style="background:url(images/user-signup-bg.jpg) no-repeat left top; ">
<h2>SIGN UP</h2>
<h5 class="setp-tag">Step 1 of 2</h5>
<h6>Registered users have access to all MoneyBoy features. This is not a Moneyboy Profile.<br>
If you’d like to create a Moneyboy Profile please click here.</h6>
<form class="user-signup-form" action="./api/user/signup" method="POSt" #submit.prevent="addUser()">
<div class="form-group">
<label>Username</label>
<input type="text" name="username" v-model="username" placeholder="mohamed-ali" class="span3 form-control">
<span v-if="hidespan">5 - 20 characters. Letters A-Z and numbers 0-9 only. No spaces.
E.g. MikeMuscleNYC.</span>
<span v-if="errorinusername"> {{ errorinusername }}</span>
</div>
<div class="form-group">
<label>Email</label>
<input type="email" name="email" v-model="email" placeholder="mohamed-ali#gmail.com" class="span3 form-control">
<span v-if="errorinemail"> {{ errorinemail }}</span>
</div>
<div class="form-group">
<label>Create a password</label>
<input type="password" name="password" v-model="password" placeholder="**********" class="span3 form-control">
<span v-if="errorinusername"> {{ errorinpassword}}</span>
</div>
<div class="form-group turms">
<input name="" type="checkbox" value="1" v-model="checked" id="terms"><label for="terms">I am over 18 and agree to the
Terms & Conditions</label>
<!--<label><input type="checkbox" name="terms">I am over 18 and agree to the Terms & Conditions.</label>-->
<input type="submit" :disabled="!checked" value="SIGN UP NOW" class="btn btn-primary w-100">
</div>
<div class="form-group">
<p>If you’d like to create a Moneyboy Profile click here.</p>
</div>
<div class="clearfix"></div>
</form>
</div>
</div>
</div>
</div>
<usersignup2component #recordadded="openusersignup2modal()"></usersignup2component>
</div>
<!--sction user-signup 1-->
</template>
<!--sript -->
<script>
Vue.component('usersignup2component', require('./UserSignup2Component.vue').default);
export default {
data(){
return {
username: '',
email:'',
password:'',
checked: false,
errorinusername: '',
errorinemail: '',
errorinpassword: '',
hidespan: true,
}
},
methods:{
addUser(){
axios.post('./api/user/signup', {
username:this.username,
email:this.email,
password:this.password
})
.then((response) =>{
this.$emit('recordadded');
})
.catch((error) => {
console.log(error.response);
this.hidespan = false;
this.errorinusername = error.response.data.errors.username;
this.errorinemail = error.response.data.errors.email;
this.errorinpassword = error.response.data.errors.password;
});
},
openusersignup2modal(){
console.log('okkkkkkkkkkkkkk');
}
},
mounted() {
console.log('UserSignUp1Component mounted.')
}
}
</script>
What I am doing wrong. I tried to console.log() on openusersignup2modal method to see, if it this function ever called or not. Found no activity on openusersignup2modal()
I'm using Vuejs2 and vee-validate for form validation. It's a great package, however I'm struggling to implement a conditional required field.
When a particular radio option is selected, I want two select fields to be required. And when that radio is not selected, I want the two select fields to be optional.
I've tried using the attach and detach methods. I can successfully detach the validation. And I can see when I attach a field it appears in the fields object. But it's not picked up by the validator.
Here is my code:
<template>
<form class="ui form" role="form" method="POST" action="/activate" v-on:submit.prevent="onSubmit" :class="{ 'error': errors.any() }">
<div class="ui segment">
<h4 class="ui header">Basic Company Information</h4>
<div class="ui message">
<p>Lorem ipsum dolor sit amet, consectetur adipiscing elit.</p>
</div>
<div class="field" :class="{ 'error': errors.has('name') }">
<div class="ui labeled input">
<label class="ui label" for="name">
Company
</label>
<input id="name" type="text" name="name" v-validate="'required'" v-model="name">
</div>
</div>
<div class="ui error message" v-show="errors.has('name')">
<p>{{ errors.first('name') }}</p>
</div>
<div class="grouped fields" :class="{ 'error': errors.has('organisation_type_id') }">
<label for="organisation_type_id">Organisation type</label>
<div class="field">
<div class="ui radio checkbox">
<input class="hidden" type="radio" name="organisation_type_id" value="1" data-vv-as="organisation type" v-validate="'required'" v-model="organisation_type">
<label>Buyer</label>
</div>
</div>
<div class="field">
<div class="ui radio checkbox">
<input class="hidden" type="radio" name="organisation_type_id" value="2" checked>
<label>Seller</label>
</div>
</div>
</div>
<div class="ui error message" v-show="errors.has('organisation_type_id')">
<p>{{ errors.first('organisation_type_id') }}</p>
</div>
<div v-show="organisation_type == '2'">
<div class="field" :class="{ 'error': errors.has('countries[]') }">
<label for="countries">Countries</label>
<select class="ui fluid search dropdown" id="countries" name="countries[]" multiple data-vv-as="countries" v-validate="'required'">
<option v-for="country in countries" :value="country.value">{{ country.text }}</option>
</select>
</div>
<div class="ui error message" v-show="errors.has('countries[]')">
<p>{{ errors.first('countries[]') }}</p>
</div>
<div class="ui message field-description">
<p>Select all the countries you export to.</p>
</div>
<div class="field" :class="{ 'error': errors.has('ciphers[]') }">
<label for="ciphers">Ciphers</label>
<select class="ui fluid search dropdown" id="ciphers" name="ciphers[]" multiple data-vv-as="ciphers" v-validate="'required'">
<option v-for="cipher in ciphers" :value="cipher.value">{{ cipher.text }}</option>
</select>
</div>
<div class="ui error message" v-show="errors.has('ciphers[]')">
<p>{{ errors.first('ciphers[]') }}</p>
</div>
<div class="ui message field-description">
<p>Select all the ciphers you support.</p>
</div>
</div> <!-- End organisation_type_id -->
<button class="ui fluid green button" type="submit">Continue</button>
</div> <!-- .ui.segment -->
</form>
</template>
<script>
export default {
props: ['countriesJson', 'ciphersJson'],
data() {
return {
name: null,
organisation_type: '2',
countries: [],
ciphers: [],
}
},
watch: {
organisation_type: function(value) {
var vm = this
if (value == '2') {
vm.$validator.attach('countries[]', 'required');
const select = document.getElementById('countries');
select.addEventListener('change', function() {
vm.$validator.validate('required', this.value);
});
vm.$validator.attach('ciphers[]', 'required');
const select = document.getElementById('ciphers');
select.addEventListener('change', function() {
vm.$validator.validate('required', this.value);
});
} else {
vm.$validator.detach('countries[]')
vm.$validator.detach('ciphers[]')
}
},
},
mounted() {
this.countries = JSON.parse(this.countriesJson)
this.ciphers = JSON.parse(this.ciphersJson)
},
methods: {
onSubmit: function(e) {
this.$validator.validateAll().then(success => {
e.target.submit()
}).catch(() => {
return
})
}
}
}
</script>
May be you mean something like this?
<input id="name"
type="text"
name="name"
v-validate="{ required: this.isRequired }"
v-model="name">
Where "isRequired" is computed field, which depend from condition
<input id="name"
type="text"
name="name"
v-validate=" isRequired ? 'required' : '' "
v-model="name">
In my case it worked by giving above condition.. Also it is helpful in case of multiple validation rules... e.g. 'required|integer|between:18,99'..
Adding {} will break the expression
you can simply use
v-validate="`required_if:${condition}`"