How can I create an array of id's from the selected option in vue-multiselect plugin? - laravel

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>

Related

Error: Objects are not valid as a React child (found: \[object Promise\]). If you meant to render a collection of children, use an array instead."

I am making a project using Next js 13 beta version. I know all the components are server components so when I use useState, I need to write "use client" statement at the top but in this case, I got "Error: Objects are not valid as a React child (found: [object Promise]). If you meant to render a collection of children, use an array instead."
"use client";
import { useRouter } from "next/navigation"
import { useState } from "react"
async function addNewStudent(sInfo, refresh){
await fetch('/api/students', {
method: "POST",
body: JSON.stringify(sInfo)
});
refresh()
}
export default async function Student() {
const router = useRouter()
const [sInfo, setSInfo] = useState({
sName:"",
sSurname:"",
sMobile:"",
sEmail:"",
sAddress:"",
sClass:""
})
const handleChange = (event) => {
setSInfo({ ...sInfo, [event.target.name]: event.target.value });
};
const handleSubmit = async (e) => {
e.preventDefault()
await addNewStudent(sInfo, router.refresh)
}
return (
<form onSubmit={handleSubmit} className="relative bg-white rounded-lg shadow dark:bg-gray-700">
<div className="flex items-start justify-between p-4 border-b rounded-t dark:border-gray-600">
<h3 className="text-xl font-semibold text-gray-900 dark:text-white">
Edit Student
</h3>
<button type="button" className="text-gray-400 bg-transparent hover:bg-gray-200 hover:text-gray-900 rounded-lg text-sm p-1.5 ml-auto inline-flex items-center dark:hover:bg-gray-600 dark:hover:text-white" data-modal-hide="editUserModal">
<svg aria-hidden="true" className="w-5 h-5" fill="currentColor" viewBox="0 0 20 20" xmlns="http://www.w3.org/2000/svg"><path fill-rule="evenodd" d="M4.293 4.293a1 1 0 011.414 0L10 8.586l4.293-4.293a1 1 0 111.414 1.414L11.414 10l4.293 4.293a1 1 0 01-1.414 1.414L10 11.414l-4.293 4.293a1 1 0 01-1.414-1.414L8.586 10 4.293 5.707a1 1 0 010-1.414z" clip-rule="evenodd"></path></svg>
</button>
</div>
<div className="p-6 space-y-6">
<div className="grid grid-cols-12 gap-6">
<div className="col-span-12 sm:col-span-4">
<label htmlFor="first-name" className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Name</label>
<input type="text" value={sInfo.sName} onChange={handleChange} name="sName" id="first-name" className="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-600 focus:border-blue-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="student name" />
</div>
<div className="col-span-12 sm:col-span-4">
<label htmlFor="last-name" className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Lastname</label>
<input type="text" value={sInfo.sSurname} onChange={handleChange} name="sSurname" id="last-name" className="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-600 focus:border-blue-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="student lastname" />
</div>
<div className="col-span-12 sm:col-span-4">
<label htmlFor="email" className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Email</label>
<input type="email" value={sInfo.sEmail} onChange={handleChange} name="sEmail" id="email" className="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-600 focus:border-blue-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="email" />
</div>
<div className="col-span-12 sm:col-span-4">
<label htmlFor="phone-number" className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Mobile</label>
<input type="number" value={sInfo.sMobile} onChange={handleChange} name="sMobile" id="phone-number" className="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-600 focus:border-blue-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="mobile" />
</div>
<div className="col-span-12 sm:col-span-4">
<label htmlFor="class" className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Class</label>
<select id="class" value={sInfo.sClass} onChange={handleChange} name="sClass" className="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-500 focus:border-blue-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500">
<option selected>Class</option>
<option value="5">5. Sınıf</option>
<option value="6">6. Sınıf</option>
<option value="7">7. Sınıf</option>
<option value="8">8. Sınıf</option>
<option value="9">9. Sınıf</option>
<option value="10">10. Sınıf</option>
<option value="11">11. Sınıf</option>
<option value="12">12. Sınıf</option>
</select>
</div>
<div className="col-span-12 sm:col-span-4">
<label for="department" className="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Address</label>
<input type="text" value={sInfo.sAddress} onChange={handleChange} name="sAddress" id="department" className="shadow-sm bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-blue-600 focus:border-blue-600 block w-full p-2.5 dark:bg-gray-600 dark:border-gray-500 dark:placeholder-gray-400 dark:text-white dark:focus:ring-blue-500 dark:focus:border-blue-500" placeholder="address" />
</div>
</div>
</div>
<div className="flex items-center p-6 space-x-2 border-t border-gray-200 rounded-b dark:border-gray-600">
<button type="submit" className="text-white bg-blue-700 hover:bg-blue-800 focus:ring-4 focus:outline-none focus:ring-blue-300 font-medium rounded-lg text-sm px-5 py-2.5 text-center dark:bg-blue-600 dark:hover:bg-blue-700 dark:focus:ring-blue-800">Save all</button>
</div>
</form>
)
}
When I delete the statement "use client", I got "You're importing a component that needs useState. It only works in a Client Component but none of its parents are marked with "use client", so they're Server Components by default."

How can I show data names field in vue-multiselect plugin in edit page?

I have a vue laravel SPA, and was working on the edit page of employees page. I already have create employees page and can display data on the vue-multiselect plugin (https://vue-multiselect.js.org/). Right now, I can display the employee id's from an array in vue-multiselect in the edit page. How can I format it to show employee names?
<style src="vue-multiselect/dist/vue-multiselect.min.css"></style>
<script>
import Multiselect from 'vue-multiselect'
export default {
components: { Multiselect },
data() {
return {
employee: {
designation_id: [],
position_id: [],
},
designation_names: {},
position_names: {}
}
},
methods: {
updateEmployee() {
this.axios
.patch(`/api/employees/${this.$route.params.id}`, this.employee)
.then((res) => {
this.$router.push({ name: 'employees' });
});
},
async getDesignations(id) {
const { data } = await this.axios.get(`/employees/${id}/designations`);
this.$set(this.designation_names, id, data.join(', '));
},
async getPositions(id) {
const { data } = await this.axios.get(`/employees/${id}/positions`);
this.$set(this.position_names, id, data.join(', '));
},
},
created() {
this.axios
.get(`/api/employees/${this.$route.params.id}`)
.then((res) => {
this.employee = res.data;
});
for(const row of this.rows) { this.getDesignations(row.id); }
for(const row of this.rows) { this.getPositions(row.id); }
},
}
</script>
<template>
<form #submit.prevent="updateEmployee">
<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 required" for="designation_id">Designation</label>
<multiselect
v-model="employee.designation_id"
:options="designation_options"
:custom-label="opt => designation_options.find(designation => designation.id == opt).name"
:multiple="true"
:taggable="true"
></multiselect>
</div>
<div class="md:w-3/6 mb-4 flex-1">
<label class="block text-gray-700 text-sm font-bold mb-2 required" for="position_id">Position</label>
<multiselect
v-model="employee.position_id"
:options="position_options"
:multiple="true"
:taggable="true"
></multiselect>
</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">Update</button>
</form>
</template>
I've managed to solve this by retrieving each field, instead of the previous code which I retrieved all in a single object.
this.axios
.get(`/api/designations/${this.$route.params.id}`)
.then((res) => {
this.form.name = res.data.name;
this.form.description = res.data.description;
});
Before:
this.axios
.get(`/api/designations/${this.$route.params.id}`)
.then((res) => {
this.form= res.data;
});

validation depends on radio button selection laravel

I have different inputs depends on radio buttons. How to validate them according to selection?
<div class="sm:col-span-2">
<div class="mt-4">
<nav class=" " aria-label="Tabs">
<div class="border-gray-300 border-2 rounded-lg pl-3 py-2 w-40" :class="tab == 'tab1' ? ' bg-green-200 border-green-500 ' : ''">
<input type="radio" #click="tab = 'tab1'" checked="tab == 'tab1' ? true: false" name="person_company"> <span class="text-gray-600 font-medium text-sm pl-2">person</span> </input>
</div>
<br>
<div class="border-gray-300 border-2 rounded-lg pl-3 py-2 w-40" :class="tab == 'tab2' ? ' bg-green-200 border-green-500 ' : ' '">
<input type="radio" #click="tab = 'tab2'" name="person_company"> <span class="text-gray-600 font-medium text-sm pl-2">company</span> </input>
</div>
</nav>
</div>
</div>
<div class="sm:col-span-2 " x-show="tab == 'tab1'">
<label for="identity_no" class="block text-sm font-medium text-gray-700">Identity</label>
<div class="mt-1">
<input type="text" name="identity_no" id="identity_no" class="block w-full py-4 border-gray-300 rounded-md shadow-sm focus:ring-green-500 focus:border-green-500 sm:text-sm">
</div>
</div>
<div class="sm:col-span-2" x-show="tab == 'tab2'">
<label for="company" class="block text-sm font-medium text-gray-700">Company name</label>
<div class="mt-1">
<input type="text" name="company" id="company" class="block w-full py-4 border-gray-300 rounded-md shadow-sm focus:ring-green-500 focus:border-green-500 sm:text-sm">
</div>
</div>
this code needs both of them that's not what I want
$this->validate($request,[
'identity' => 'required',
'company' => 'required',
]);
You should use jquery to manage it. First of all, you will have to take values to radio inputs. And then apply the required property through jquery condition.
<input type="radio" #click="tab = 'tab1'" checked="tab == 'tab1' ? true: false" name="person_company" value = "tab1"> <span class="text-gray-600 font-medium text-sm pl-2">person</span> </input>
<input type="radio" #click="tab = 'tab2'" name="person_company"> <span class="text-gray-600 font-medium text-sm pl-2" value = "tab2">company</span> </input>
$('input[type=radio][name= person_company]').change(function() {
if (this.value == 'tab1') {
$("#identity_no").prop('required',true);
$("#company").prop('required',false);
}
else if (this.value == 'tab2') {
$("#company").prop('required',true);
$("#identity_no").prop('required',false);
}
});

Laravel resource controller with AJAX form validation

I want to validate the form with AJAX, because when the normal validation fails, the uploaded files are gone.
I get a JSON response but at the working URL: /properties, instead of the form properties/create.
This is an example of the response:
{"error":{"title":["The title must be at least 10 max:50 characters."],"asking_price":["The asking price must be at least 10000."],"description":["The description must be at least 100 characters."],"feat_image_path":["The feat image path has invalid image dimensions."]}}
I tried a lot of things, but none is working.
Am I doing something wrong logically, or is it the URL of the AJAX script??
Thanks in advance, Sander
This is the blade file with the AJAX script.
#section('tinymce')
<script src="https://cdn.tiny.cloud/1/izqu9favecmjvbbfp1dhe96fphutb1stn4aqs7363k6j8trm/tinymce/5/tinymce.min.js" referrerpolicy="origin"></script>
<script>
tinymce.init({
selector: '#description'
});
</script>
#stop
<x-slot name="header">
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
{{ __('Properties') }}
</h2>
</x-slot>
<div class="py-12">
<div class=" mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-6 bg-white border-b border-gray-200">
<h1 class="text-2xl px-12 font-bold w-full my-4">Add Property<span class="text-sm ml-2 text-red-500 italic">* is required</span></h1>
<div class="container my-4 xl:text-lg text-center">
<div class="w-full mx-auto">
#if ($errors->any())
<div class="alert alert-danger">
<ul>
#foreach ($errors->all() as $error)
<li>{{ $error }}</li>
#endforeach
</ul>
</div>
#endif
<div class="alert alert-danger print-error-msg" style="display:none">
<ul></ul>
</div>
{{-- Add Porperty Form --}}
<form action="../properties" method="post" enctype="multipart/form-data" id="create_property_form" class="bg-white shadow-md rounded mb-4 xl:mb-8 w-full">
#csrf
<h2 class="text-center text-xl font-bold w-full my-4">General Information</h2>
{{-- Title --}}
<div class="form-wrapper w-full flex flex-wrap px-8">
<div class="mb-4 xl:mb-8 w-full xl:w-1/2 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="title">
Property Title*
</label>
<input class="block shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="title" type="text" placeholder="Title of the property" name="title" value="{{ old('title') }}" required>
<span class="error title-error"></span>
</div>
{{-- Asking Price --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/2 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="asking_price">
Asking Price*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="asking_price" name="asking_price" type="number" placeholder="Price in $ USD" value="{{ old('asking_price') }}" required>
<span class="error asking_price-error"></span>
</div>
<h2 class="text-center text-xl font-bold w-full my-4">Adress</h2>
{{-- Street --}}
<div class="mb-4 xl:mb-8 w-full xl:w-2/3 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="street">
Street*
</label>
<input class="block shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="street" name="street" type="text" placeholder="Name of the street" value="{{ old('street') }}" required>
<span class="error street-error"></span>
</div>
{{-- Number --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/3 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="number">
Number*
</label>
<input class="block shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="number" name="number" type="text" placeholder="Appt/house number" value="{{ old('number') }}" required>
<span class="error number-error"></span>
</div>
{{-- Zip Code --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/3 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="zip_code">
Zip Code
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="zip_code" name="zip_code" type="text" placeholder="Zip / Postal code" value="{{ old('zip_code') }}">
<span class="error zip_code-error"></span>
</div>
{{-- City --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/3 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="city">
City*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="city" name="city" type="text" placeholder="eg. 'New Tork'" value="{{ old('city') }}" required>
<span class="error city-error"></span>
</div>
{{-- Location --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/3 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="location">
Location*
</label>
<select name="location_id" id="location_id" class="w-full">
#foreach ($locations as $location)
<option value="{{ $location->id }}">{{ $location-> name}}</option>
#endforeach
</select>
</div>
{{-- Coördinates --}}
<h2 class="text-center text-xl font-bold w-full my-4">Position<span class="text-sm ml-2 text-gray-500">Get coördinates with Google Maps or Latlong </span></h2>
{{-- Latitude --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/2 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="latitude">
Latitude*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="latitude" name="latitude" min="11.979144" max="18.145982" step="0.000001" type="number" placeholder="eg. 12.123456" value="{{ old('latitude') }}" required>
<span class="error latitude-error"></span>
</div>
{{-- Longitude --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/2 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="longitude">
Longitude*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="longitude" name="longitude" min="-68.440281" max="-62.966999" step="0.000001" type="number" placeholder="eg. -64.123456" value="{{ old('longitude') }}" required>
<span class="error longitude-error"></span>
</div>
{{-- Details --}}
<h2 class="text-center text-xl font-bold w-full my-4">Property Details</h2>
{{-- Built Year --}}
<div class="mb-4 xl:mb-8 w-full xl:w-4/12 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="built_in">
Built in Year*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="built_in" name="built_in" min="1900" step="1" type="number" placeholder="YYYY" value="{{ old('built_in') }}" required>
<span class="error built_in-error"></span>
</div>
{{-- Indoor Area --}}
<div class="mb-4 xl:mb-8 w-full xl:w-4/12 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="area_size_indoor">
Indoor Area Size*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="area_size_indoor" name="area_size_indoor" type="number" placeholder="Size in sqm (m2)" step="1" value="{{ old('area_size_indoor') }}" required>
<small>1 sqft = 0.09290304 sqm</small>
<span class="error area_size_indoor-error"></span>
</div>
{{-- Outdoor Area --}}
<div class="mb-4 xl:mb-8 w-full xl:w-4/12 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="area_size_outdoor">
Outdoor Area Size*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="area_size_outdoor" name="area_size_outdoor" type="number" placeholder="Size in sqm (m2)" step="1" value="{{ old('area_size_outdoor') }}" required>
<small>1 sqft = 0.09290304 sqm</small>
<span class="error area_size_outdoor-error"></span>
</div>
{{-- Bedrooms --}}
<div class="mb-4 xl:mb-8 w-full xl:w-4/12 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="bedrooms">
Bedrooms*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="bedrooms" name="bedrooms" type="number" step="1" value="{{ old('bedrooms') }}" required>
<span class="error bedrooms-error"></span>
</div>
{{-- Bathrooms --}}
<div class="mb-4 xl:mb-8 w-full xl:w-4/12 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="bathrooms">
Bathrooms*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="bathrooms" name="bathrooms" type="number" step="1" value="{{ old('bathrooms') }}" required>
<span class="error bathrooms-error"></span>
</div>
{{-- Property Type --}}
<div class="mb-4 xl:mb-8 w-full xl:w-4/12 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="property_type">
Property Type*
</label>
<select name="property_type" id="property_type" class="w-full">
<option value="Villa">Villa</option>
<option value="Chalet">Chalet</option>
<option value="Appartment">Appartment</option>
<option value="Condo">Condo</option>
<option value="Lot">Lot</option>
<option value="Penthouse">Penthouse</option>
</select>
</div>
{{-- Desciption --}}
<div class="mb-4 xl:mb-8 w-full">
<label class="block text-gray-500 text-base font-bold mb-2" for="description">
Description*
</label>
<textarea class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="description" name="description">
{{ old('description') }}
</textarea>
<span class="error description-error"></span>
</div>
{{-- Featured Image --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/2 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="feat_image_path">
Featured Image*
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" id="feat_image_path" name="feat_image_path" type="file" value="{{ old('feat_image_path') }}" required>
<span class="error feat_image_path-error"></span>
</div>
{{-- Gallery Images --}}
<div class="mb-4 xl:mb-8 w-full xl:w-1/2 px-4">
<label class="block text-gray-500 text-base font-bold mb-2" for="bathrooms">
Gallery Images
</label>
<input class="shadow appearance-none border rounded w-full py-2 px-3 text-gray-500 leading-tight focus:outline-none focus:shadow-outline" type="file" name="file[]" id="file" required="" multiple>
<span class="error file-error"></span>
</div>
{{-- Submit --}}
<div class=" mb-4 xl:mb-8 mx-auto w-48">
<input class="py-2 bg-green-300 hover:bg-green-200 text-white w-full font-bold rounded shadow" data-resource="" value="Submit Property" type="submit">
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</div>
The AJAX script:
$(document).ready(function() {
$("#create_property_form").click(function(e) {
e.preventDefault();
let _token = $("input[name='_token']").val();
let title = $("input[name='asking_price']").val();
let latitude = $("input[name='latitude']").val();
let longitude = $("input[name='longitude']").val();
let description = $("textarea[name='description']").val();
let feat_image_path = $("textarea[name='feat_image_path']").val();
$.ajax({
url: "{{ url('/properties/create') }}"
, type: 'POST'
, data: {
_token: _token
, title: title
, latitude: latitude
, longitude: longitude
, description: description
, feat_image_path: feat_image_path
}
success: function(data) {
console.log(data.error)
if ($.isEmptyObject(data.error)) {
alert(data.success);
} else {
printErrorMsg(data.error);
}
}
});
});
function printErrorMsg(msg) {
$.each(msg, function(key, value) {
console.log(key);
$('.' + key + '_err').text(value);
});
}
});
I have one route for the resource controller:
Route::resource('properties', 'App\Http\Controllers\User\PropertyController');
My goal is to only show errors, when no error I add everything in the DB.
Here is the store method:
public function store(Request $request)
{
// Validate input
$validator = Validator::make($request->all(),[
'title' => 'required|unique:properties|min:10 max:50',
'asking_price' => 'required|numeric|min:10000|max:1000000000',
'street' => 'required|min:3',
'number' => 'required',
'city' => 'required|min:3',
'latitude' => 'required|between:9,12',
'longitude' => 'required|between:9,12',
'built_in' => 'required|numeric',
'area_size_indoor' => 'required|numeric',
'area_size_outdoor' => 'required|numeric',
'bedrooms' => 'required|numeric',
'bathrooms' => 'required|numeric',
'description' => 'required|min:100',
'feat_image_path' => 'required|image|dimensions:min_width=1500,min_height=800|max:2500',
]);
if ($validator->passes()) {
return response()->json(['success'=>'Added new records.']);
}
return response()->json(['error'=>$validator->errors()]);
// Generate random number for filename
$random = rand(1111,9999) * rand(1, 9);
// Validate Featured Image
if($request->hasFile('feat_image_path'))
{
// Make a full size imaye
ImageIvn::make($request->feat_image_path)->resize(1500,800)->save(public_path('img/' . $random . '_feat.jpg'))
->resize(400,300)->save(public_path('img/' . $random . '_feat_thumb.jpg'));
}
// Store Property
$property = new Property([
'title' => $request->title,
'slug' => Str::slug($request->title),
'user_id' => Auth::id(),
'street' => $request->street,
'number' => $request->number,
'zip_code' => $request->zip_code,
'city' => $request->city,
'asking_price' => $request->asking_price,
'status' => 'For Sale',
'location_id' => $request->location_id,
'property_type' => $request->property_type,
'latitude' => $request->latitude,
'longitude' => $request->longitude,
'built_in' => $request->built_in,
'area_size_indoor' => $request->area_size_indoor,
'area_size_outdoor' => $request->area_size_outdoor,
'bedrooms' => $request->bedrooms,
'bathrooms' => $request->bathrooms,
'description' => $request->description,
'feat_image_path' => 'img/' . $random . '_feat.jpg',
]);
$property->save();
/**
* Uploaded gallery images are stored with the use of the property ID as FK
*/
// Validate Gallery Images
if($request->hasFile('file'))
{
$request->validate([
'file.*' => 'image'
]);
$files = $request->file('file');
// Generate images
foreach($files as $file) {
// Generate random number for filename
$rand = $property->id . '-' . rand(99,999) * rand(99,999);
// Create Full size image
ImageIvn::make($file)->resize(1200,900)->save(public_path('img/' . $rand . '_full.jpg'));
// Save in DB
$image = new Image([
'property_id' => $property->id,
'image_path' => 'img/' . $rand . '_full.jpg',
'size' => 'full',
]);
$image->save();
// Create thumbnail size image
ImageIvn::make($file)->resize(1200,900)->save(public_path('img/' . $rand . '_thumb.jpg'));
// Store in DB
$image = new Image([
'property_id' => $property->id,
'image_path' => 'img/' . $rand . '_thumb.jpg',
'size' => 'thumb',
]);
$image->save();
}
}
return $this->index()->with(["message" => "Property " . $property->name . " is added"]);
}

Saved date does not show up in the form

I'm using laravel livewire and I've created a page that you can select a date for when you want the post
to publish. When I create a new post and save the date then it saves fine in the database, but if I try
to edit the post and change the date the date that I saved in the database isn't showing in the form.
Here is my code.
My EditPost.php
<?php
namespace App\Http\Livewire;
use App\Models\Post;
use Livewire\Component;
class EditPost extends Component
{
public $name;
public $publishDate;
public Post $post;
public function mount(Post $post)
{
$this->name = $post->name;
$this->publishDate = $post->publish_date;
}
public function render()
{
return view('livewire.edit-post');
}
}
and this is my edit.blade.php
<div>
<div class="mt-10 sm:mt-0">
<div class="md:grid md:grid-cols-3 md:gap-6">
<div class="md:col-span-1">
<div class="px-4 sm:px-0">
<h3 class="text-lg font-medium leading-6 text-gray-900">Edit Post</h3>
</div>
</div>
<div class="mt-5 md:mt-0 md:col-span-2">
<div class="form">
<div class="shadow overflow-hidden sm:rounded-md">
<div class="px-4 py-5 bg-white sm:p-6">
<div class="grid grid-cols-6 gap-6">
<div class="col-span-6 sm:col-span-3">
<label for="name" class="block text-sm font-medium leading-5 text-gray-700">Name</label>
<input id="name" wire:model="name" class="#error('name') border border-red-500 #enderror mt-1 form-input block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5">
#error('name')
<small>
<div class="text-red-500">{{ $message }}</div>
</small>
#enderror
</div>
<div class="col-span-6 sm:col-span-4">
<label for="publish_date" class="block text-sm font-medium leading-5 text-gray-700">Publish Date</label>
<input id="publish_date" wire:model="publishDate" type="date" class="mt-1 form-input block w-full transition duration-150 ease-in-out sm:text-sm sm:leading-5">
</div>
</div>
</div>
<div class="px-4 py-3 bg-gray-50 text-right sm:px-6">
<button wire:click="editPost" class="py-2 px-4 border border-transparent text-sm leading-5 font-medium rounded-md text-white bg-indigo-600 shadow-sm hover:bg-indigo-500 focus:outline-none focus:shadow-outline-blue active:bg-indigo-600 transition duration-150 ease-in-out">
Save
</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>

Resources