Unable to insert data in the database in laravel projet with vuejs and vuetify - laravel

I have setup a laravel project with Vuejs and vuetify to insert data in the database. But for some reason I not able to insert data in the database. When I compile my code I can see no error but when I inspect my code I can see error in my console saying "Internal service error" . I assuming that the error may be in my controller.
Here are m code:
Location.vue
<template>
<v-app id="inspire">
<v-data-table
item-key="code"
class="elevation-1"
color="error"
:loading = "loading"
loading-text="Loading... Please wait"
:headers="headers"
:options.sync="options"
:server-items-length="locations.total"
:items="locations.data"
show-select
#input="selectAll"
:footer-props="{
itemsPerPageOptions: [5,10,15],
itemsPerPageText: 'Roles Per Page',
'show-current-page': true,
'show-first-last-page': true
}"
>
<template v-slot:top>
<v-toolbar flat color="dark">
<v-toolbar-title>My Stage</v-toolbar-title>
<v-divider
class="mx-4"
inset
vertical
></v-divider>
<v-spacer></v-spacer>
<v-dialog v-model="dialog" max-width="500px">
<template v-slot:activator="{ on }">
<v-btn color="error" dark class="mb-2" v-on="on">Add New Stage</v-btn>
<v-btn color="error" dark class="mb-2 mr-2" #click="deleteAll">Delete</v-btn>
</template>
<v-card>
<v-card-title>
<span class="headline">{{ formTitle }}</span>
</v-card-title>
<v-card-text>
<v-container>
<v-row>
<v-col cols="12" sm="12" >
<v-text-field autofocus color="error" v-model="editedItem.code" label="Code"></v-text-field>
</v-col>
<v-col cols="12" sm="12" >
<v-text-field autofocus color="error" v-model="editedItem.name" label="Name"></v-text-field>
</v-col>
<v-col cols="12" sm="12" >
<v-text-field autofocus color="error" v-model="editedItem.description" label="Description"></v-text-field>
</v-col>
</v-row>
</v-container>
</v-card-text>
<v-card-actions>
<v-spacer></v-spacer>
<v-btn color="error darken-1" text #click="close">Cancel</v-btn>
<v-btn color="error darken-1" text #click="save">Save</v-btn>
</v-card-actions>
</v-card>
</v-dialog>
</v-toolbar>
<v-row>
<v-col cols="12">
<v-text-field #input="searchIt" label="Search..." class="mx-4" ></v-text-field>
</v-col>
</v-row>
</template>
<template v-slot:item.action="{ item }">
<v-icon
small
class="mr-2"
#click="editItem(item)"
>
mdi-content-save-edit-outline
</v-icon>
<v-icon
small
#click="deleteItem(item)"
>
mdi-delete
</v-icon>
</template>
<template v-slot:no-data>
<v-btn color="error" #click="initialize">Reset</v-btn>
</template>
</v-data-table>
<v-snackbar v-model="snackbar" >
{{text}}
<v-btn
color="error"
text
#click="snackbar = false"
>
Close
</v-btn>
</v-snackbar>
</v-app>
</template>
<script>
export default {
data: () => ({
dialog: false,
loading: false,
snackbar: false,
selected: [],
text: '',
options:{
itemsPerPage: 5,
sortBy:['id'],
sortDesc: [false]
},
headers: [
{text: '#',align: 'left', sortable: false,value: 'id'},
{ text: 'Code', value: 'code' },
{ text: 'Name', value: 'name' },
{ text: 'Description', value: 'description' },
{ text: 'Actions', value: 'action'},
],
locations: [],
editedIndex: -1,
editedItem: {
id: '',
code: '',
name: '',
description: '',
},
defaultItem: {
id: '',
code: '',
name: '',
description: '',
},
}),
computed: {
formTitle () {
return this.editedIndex === -1 ? 'New Stage' : 'Edit Stage'
},
},
watch: {
dialog (val) {
val || this.close()
},
options:{
handler(e){
console.dir(e);
const sortBy = e.sortBy.length>0 ? e.sortBy[0].trim() : 'id';
const orderBy = e.sortDesc[0] ? 'desc' : 'asc';
axios.get(`/api/locations`,{params:{'page':e.page, 'per_page':e.itemsPerPage, 'sort_by': sortBy, 'order_by': orderBy}})
.then(res => {
this.locations = res.data.locations
})
},
deep: true
}
},
created () {
this.initialize()
},
methods: {
selectAll(e){
this.selected = [];
if(e.length > 0){
this.selected = e.map(val => val.id)
}
},
deleteAll(){
let decide = confirm('Are you sure you want to delete these items?')
if(decide){
axios.post('/api/locations/delete', {'locations': this.selected})
.then(res => {
this.text = "Records Deleted Successfully!";
this.selected.map(val => {
const index = this.locations.data.indexOf(val)
this.locations.data.splice(index, 1)
})
this.snackbar = true
}).catch(err => {
console.log(err.response)
this.text = "Error Deleting Record"
this.snackbar=true
})
}
},
searchIt(e){
if(e.length > 3){
axios.get(`/api/locations/${e}`)
.then(res => this.locations = res.data.locations)
.catch(err => console.dir(err.response))
}
if(e.length<=0){
axios.get(`/api/locations`)
.then(res => this.locations = res.data.locations)
.catch(err => console.dir(err.response))
}
},
paginate(e){
const sortBy = e.sortBy.length>0 ? e.sortBy[0].trim() : 'code';
const orderBy = e.sortDesc[0] ? 'desc' : 'asc';
axios.get(`/api/locations`,{params:{'page':e.page, 'per_page':e.itemsPerPage, 'sort_by': sortBy, 'order_by': orderBy}})
.then(res => {
this.locations = res.data.locations
})
},
initialize () {
// Add a request interceptor
axios.interceptors.request.use((config) => {
this.loading = true;
return config;
}, (error) => {
this.loading = false;
return Promise.reject(error);
});
// Add a response interceptor
axios.interceptors.response.use( (response) => {
this.loading = false;
return response;
}, (error) => {
this.loading = false
return Promise.reject(error);
});
},
editItem (item) {
this.editedIndex = this.locations.data.indexOf(item)
this.editedItem = Object.assign({}, item)
this.dialog = true
},
deleteItem (item) {
const index = this.locations.data.indexOf(item)
let decide = confirm('Are you sure you want to delete this item?')
if(decide){
axios.delete('/api/locations/'+item.id)
.then(res => {
this.text = "Record Deleted Successfully!";
this.snackbar = true
this.locations.data.splice(index, 1)
}).catch(err => {
console.log(err.response)
this.text = "Error Deleting Record"
this.snackbar=true
})
}
},
close () {
this.dialog = false
setTimeout(() => {
this.editedItem = Object.assign({}, this.defaultItem)
this.editedIndex = -1
}, 300)
},
save () {
if (this.editedIndex > -1) {
const index = this.editedIndex
axios.put('/api/locations/'+this.editedItem.id, {'code': this.editedItem.code, 'name': this.editedItem.name, 'description': this.editedItem.description})
.then(res => {
this.text = "Record Updated Successfully!";
this.snackbar = true;
Object.assign(this.locations.data[index], res.data.location)
})
.catch(err => {
console.log(err.response)
this.text = "Error Updating Record"
this.snackbar=true
})
// Object.assign(this.locations[this.editedIndex], this.editedItem)
} else {
axios.post('/api/locations',{'code': this.editedItem.code, 'name': this.editedItem.name, 'description': this.editedItem.description})
.then(res => {
this.text = "Record Added Successfully!";
this.snackbar=true;
this.locations.data.push(res.data.location)
})
.catch(err => {
console.dir(err.response)
this.text = "Error Inserting Record"
this.snackbar=true
})
}
this.close()
},
},
}
</script>
<style scoped></style>
Location.php
<?php
namespace App;
use Illuminate\Database\Eloquent\Model;
class Location extends Model
{
protected $guarded = [];
}
LocationController.php
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Location;
class LocationController extends Controller
{
public function index(Request $request)
{
$per_page = $request->per_page ? $request->per_page : 5;
$sort_by = $request->sort_by;
$order_by = $request->order_by;
return response()->json(['locations' => Location::orderBy($sort_by, $order_by)->paginate($per_page)],200);
}
public function store(Request $request)
{
$location= Location::create([
'code' =>$request->code
'name' =>$request->name
'description' =>$request->description
]);
return response()->json(['location'=>$location],200);
}
public function show($id)
{
$locations = Location::where('code', 'name','description''LIKE', "%$id%")->paginate();
return response()->json(['locations' => $locations],200);
}
public function update(Request $request, $id)
{
$location = Location::find($id);
$location->code = $request->code;
$location->name = $request->name;
$location->description = $request->description;
$location->save();
return response()->json(['location'=>$location], 200);
}
public function destroy($id)
{
$location = Location::find($id)->delete();
return response()->json(['location'=>$location],200);
}
public function deleteAll(Request $request){
Location::whereIn('id', $request->locations)->delete();
return response()->json(['message', 'Records Deleted Successfully'], 200);
}
}

yeah, the issue in your LocationController.php file, you missed commas in Location::create . Also, show function has a problem. notice carefully.
<?php
namespace App\Http\Controllers\Api;
use App\Http\Controllers\Controller;
use Illuminate\Http\Request;
use App\Location;
class LocationController extends Controller
{
public function index(Request $request)
{
$per_page = $request->per_page ? $request->per_page : 5;
$sort_by = $request->sort_by;
$order_by = $request->order_by;
return response()->json(['locations' => Location::orderBy($sort_by, $order_by)->paginate($per_page)],200);
}
public function store(Request $request)
{
$location= Location::create([
'code' =>$request->code,
'name' =>$request->name,
'description' =>$request->description
]);
return response()->json(['location'=>$location],200);
}
public function show($id)
{
$locations = Location::where('code','LIKE', "%$id%")->orWhere('name','LIKE', "%$id%")->orWhere('description', 'LIKE', "%$id%")->paginate();
return response()->json(['locations' => $locations],200);
}
public function update(Request $request, $id)
{
$location = Location::find($id);
$location->code = $request->code;
$location->name = $request->name;
$location->description = $request->description;
$location->save();
return response()->json(['location'=>$location], 200);
}
public function destroy($id)
{
$location = Location::where('id', $id)->delete();
return response()->json(['location'=>$location],200);
}
public function deleteAll(Request $request){
Location::whereIn('id', $request->locations)->delete();
return response()->json(['message', 'Records Deleted Successfully'], 200);
}
}

Related

rendering events from the database with Vue3 and Inertia

I'm having rather great difficulty getting my Laravel 9 FullCalendar 5 with Vue 3 app to pull events from the database though Vue3. I'm assuming I need some help formulating the axios script in the index.vue.
Here's my Index.vue
<template>
<head title="Dashboard" />
<BreezeAuthenticatedLayout>
<template #header>
<h2 class="font-semibold text-xl text-gray-800 leading-tight">
Resource Calendar Timeline
</h2>
</template>
<div class="py-12">
<div class="max-w-10xl mx-auto sm:px-6 lg:px-8">
<div class="bg-white overflow-hidden shadow-sm sm:rounded-lg">
<div class="p-12 bg-white border-b border-gray-200">
<div class='demo-app'>
<div class='demo-app-main'>
<FullCalendar
class='demo-app-calendar'
:options='calendarOptions'
:events='calendarEvents'>
<template v-slot:eventContent='arg'>
<b>{{ arg.timeText }}</b>
<i>{{ arg.event.title }}</i>
</template>
</FullCalendar>
</div>
</div>
</div>
</div>
</div>
</div>
</BreezeAuthenticatedLayout>
</template>
<!--start calendar-->
<script setup lang='ts'>
import BreezeAuthenticatedLayout from '#/Layouts/AuthenticatedLayout.vue';
import { head, Link } from '#inertiajs/inertia-vue3';
import '#fullcalendar/core/vdom'; // solves problem with Vite
import FullCalendar from '#fullcalendar/vue3';
import dayGridPlugin from '#fullcalendar/daygrid';
import timeGridPlugin from '#fullcalendar/timegrid';
import listPlugin from '#fullcalendar/list';
import resourceTimelinePlugin from '#fullcalendar/resource-timeline';
import interactionPlugin from '#fullcalendar/interaction';
import axios from 'axios';
</script>
<script lang='ts'>
export default {
components: {FullCalendar},
data() {
return {
calendarEvents:
{
url: 'show-events'
},
calendarOptions: {
plugins: [
dayGridPlugin,
timeGridPlugin,
resourceTimelinePlugin,
listPlugin,
interactionPlugin // needed for dateClick
],
headerToolbar: {
left: 'promptResource prev,next today',
center: 'title',
right: 'resourceMonth,dayGridMonth,timeGridWeek,timeGridDay,listMonth'
},
views: {
resourceMonth: {
type: 'resourceTimelineMonth',
buttonText: 'personnel'
}
},
customButtons: {
promptResource: {
text: '+ personnel',
click: function() {
var title = prompt('Name');
if (title) {
event.addResource({
title: title
});
}
}
}
},
initialView: 'dayGridMonth',
editable: true,
selectable: true,
selectMirror: true,
dayMaxEvents: true,
weekends: true,
select: this.handleDateSelect,
eventClick: this.handleEventClick,
eventsSet: this.handleEvents
} as CalendarOptions,
currentEvents: [] as EventApi[],
}
},
methods: {
handleWeekendsToggle() {
this.calendarOptions.weekends = !this.calendarOptions.weekends // update a property
},
handleDateSelect(selectInfo: DateSelectArg) {
let title = prompt('Please enter a new title for your event')
let calendarApi = selectInfo.view.calendar
calendarApi.unselect() // clear date selection
if (title) {
calendarApi.addEvent({
id: createEventId(),
title,
start: selectInfo.startStr,
end: selectInfo.endStr,
allDay: selectInfo.allDay
})
}
},
handleEventClick(clickInfo: EventClickArg) {
if (confirm(`Are you sure you want to delete the event '${clickInfo.event.title}'`)) {
clickInfo.event.remove()
}
},
handleEvents(events: EventApi[]) {
this.currentEvents = events
},
}
}
</script>
here's my controller
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use Inertia\Inertia;
use App\Models\Appointment;
use App\Models\Booking;
use App\Models\Event;
use Illuminate\Support\Facades\Validator;
class AppointmentController extends Controller
{
/**
* Show the form for creating a new resource.
*
* #return Response
*/
public function index()
{
{
$events = array();
$bookings = Event::all();
foreach($bookings as $booking) {
$color = null;
if($booking->title == 'Test') {
$color = '#924ACE';
}
if($booking->title == 'Test 1') {
$color = '#68B01A';
}
$events[] = [
'id' => $booking->id,
'title' => $booking->title,
'start' => $booking->start_date,
'end' => $booking->end_date,
'color' => $color
];
}
//return view('calendar.index', ['events' => $events]);
return Inertia::render('Appointments/Index', ['events' => $events]);
}
}
public function showEvents(Request $request) {
$event = Event::get(['title','acronym','city','venue','value','start','end']);
return response()->json(["events" => $event]);
}
public function getEvents(Request $request) {
$events = array();
$events = Event::all();
foreach($events as $event) {
$color = null;
if($event->title == 'Test') {
$color = '#924ACE';
}
if($event->title == 'Test 1') {
$color = '#68B01A';
}
$events[] = [
'id' => $event->id,
'title' => $event->event_name,
'start' => $event->start_date,
'end' => $event->end_date,
'color' => $color
];
}
return Inertia::render('Events/Index', ['events' => $events]);
}
$events = array();
$events = Event::all();
foreach($events as $event) {
$color = null;
if($event->title == 'Test') {
$color = '#924ACE';
}
if($event->title == 'Test 1') {
$color = '#68B01A';
}
$events[] = [
'id' => $event->id,
'title' => $event->event_name,
'start' => $event->start_date,
'end' => $event->end_date,
'color' => $color
];
}
return Inertia::render('Events/Index', ['events' => $events]);
}
*/
public function store(Request $request)
{
$assignee =
($request->assignee && auth()->user()->isAdmin ?
$request->assignee :
$assignee = auth()->user()->id)->get();
$appointment = new Appointment([
'start_date' => $request->start,
'end_date' => $request->end,
'event_name' => $request->title,
'acronym' => $request->description,
'user_id' => $assignee
]);
$appointment->save();
return $event;
}
public function filter(Request $request)
{
if (auth()->user()->isAdmin) {
return Appointment::whereBetween('start', [$request->start, $request->end])
->with('user:id,name,lastname')
->get();
} else {
return Appointment::whereBetween('start', [$request->start, $request->end])
->where('user_id', auth()->user()->id)
->get();
}
}
public function update(Request $request, Appointment $appointment)
{
$user = auth()->user();
if ($appointment->user_id === $user->id || $user->isAdmin) {
$appointment->update($request->all());
} else {
abort(403);
}
}
public function destroy(Appointment $appointment)
{
$user = auth()->user();
if ($appointment->user_id === $user->id || $user->isAdmin) {
$appointment->delete();
} else {
abort(403);
}
}
}
and here's the JSON output of the events I'm trying to pull in from the 'show-events' endpoint
{"events":[{"title":"Test","acronym":"TST","city":"Denver","venue":"Ceavco","value":"$0","start":"2022-10-10 00:00:00","end":"2022-10-28 00:00:00"},{"title":"Test 2","acronym":"TST2","city":"boston","venue":"AVFX","value":"$0","start":"2022-10-05 00:00:00","end":"2022-10-07 00:00:00"}]}
What am I missing?
Something in the methods or the export on the Vue element?
Thanks to you both for steering me in the right direction. I managed to get it working with the following Index.vue:
<script setup lang='ts'>
import BreezeAuthenticatedLayout from '#/Layouts/AuthenticatedLayout.vue';
import { head, Link } from '#inertiajs/inertia-vue3';
import '#fullcalendar/core/vdom'; // solves problem with Vite
import FullCalendar from '#fullcalendar/vue3';
import dayGridPlugin from '#fullcalendar/daygrid';
import timeGridPlugin from '#fullcalendar/timegrid';
import listPlugin from '#fullcalendar/list';
import resourceTimelinePlugin from '#fullcalendar/resource-timeline';
import interactionPlugin from '#fullcalendar/interaction';
import axios from 'axios';
import { INITIAL_EVENTS, createEventId } from '#/components/event-utils.ts';
// import { INITIAL_RESOURCES, createResourceId } from '#/components/resource-utils.ts';
</script>
<script lang='ts'>
export default {
components: {FullCalendar},
data() {
return {
calendarOptions: {
plugins: [
dayGridPlugin,
timeGridPlugin,
resourceTimelinePlugin,
listPlugin,
interactionPlugin // needed for dateClick
],
events: [],
headerToolbar: {
left: 'promptResource prev,next today',
center: 'title',
right: 'resourceMonth,dayGridMonth,timeGridWeek,timeGridDay,listMonth'
},
views: {
resourceMonth: {
type: 'resourceTimelineMonth',
buttonText: 'personnel'
}
},
customButtons: {
promptResource: {
text: '+ personnel',
click: function() {
var title = prompt('Name');
if (title) {
event.addResource({
title: title
});
}
}
}
},
initialView: 'resourceTimelineMonth',
editable: true,
},
created() {
this.getEvents();
},
methods: {
getEvents() {
axios.get('show-events')
.then(response => {
this.calendarOptions.events = response.data.events;
});
},
}
</script>

RTK createEntityAdapter not getting relational data in list after save user in database

i have a list of users which getting data from database by using RTK createEntityAdapter.
API function code for getting list of users
public function index(){
$roles = Role::all();
$all_roles = [];
foreach ($roles as $key => $role) {
$obj_role = new \stdClass();
$obj_role->id = $role->id;
$obj_role->name = $role->title;
array_push($all_roles,$obj_role);
}
return response()->json([
'users' => User::with('roles')->paginate(10),
'roles' => $all_roles
]);
}
In the above code getting users and roles in response & showing list in react app by using RTK createEntityAdapter
userSlice.js
import { createSlice,createEntityAdapter} from "#reduxjs/toolkit";
import { HTTP_STATUS } from "../../src/constants";
import { fetchUsers, deleteUsers, saveUser } from "services/userService";
const userAdapter = createEntityAdapter({
selectId: (user) => user.id,
})
const userSlice = createSlice({
name:'user',
initialState: userAdapter.getInitialState(
{ loading: false,
page: 1,
total_pages: null,
status: null,
message: null,
roles: []
} ),
reducers:{
pageByNumber: (state,{payload}) => {
state.page = payload.page
},
nextPage: (state, {payload}) => {
state.page = state.page++
},
previousPage: (state, {payload}) => {
state.page = state.page--
},
clear: (state) => {
state.status = null,
state.message = null
}
},
extraReducers: {
[fetchUsers.pending]: (state) => {
state.loading = true,
state.status = HTTP_STATUS.PENDING
},
[fetchUsers.fulfilled]: (state, {payload}) => {
state.loading = false,
state.page = payload.users.current_page,
state.total_pages = Math.ceil(payload.users.total/payload.users.per_page),
userAdapter.setAll(state, payload.users.data),
state.status = HTTP_STATUS.FULFILLED,
state.roles = payload.roles
},
[fetchUsers.rejected]: (state, {error}) => {
state.loading = false,
state.status = HTTP_STATUS.REJECTED,
state.message = error.message
},
[deleteUsers.pending]: (state) => {
state.loading = true,
state.status = HTTP_STATUS.PENDING
},
[deleteUsers.fulfilled]: (state, { payload }) => {
state.loading = false,
userAdapter.removeOne(state, payload.id)
},
[deleteUsers.rejected]: (state) => {
state.loading = false
},
[saveUser.pending]: (state) => {
state.loading = true,
state.status = HTTP_STATUS.PENDING
},
[saveUser.fulfilled]: (state, { payload }) => {
state.loading = false,
state.status = HTTP_STATUS.FULFILLED
if(!payload.errors){
userAdapter.addOne(state, payload.id),
state.message = payload.message
}
},
[saveUser.rejected]: (state,{error}) => {
state.loading = false,
state.status = HTTP_STATUS.REJECTED,
state.message = error.message
}
},
});
export const userSelectors = userAdapter.getSelectors(
(state) => state.user,
)
export const {pageByNumber, nextPage, previousPage,clear} = userSlice.actions
export default userSlice.reducer
user/index.js
const roles = useSelector(state => state.user.roles);
const allUsers = useSelector(userSelectors.selectAll);
useEffect(() => {
dispatch(
fetchUsers(currentPage))
.then(unwrapResult)
.then((obj) => console.log(obj))
.catch((obj) => console.log({objErr: obj}))
}, [dispatch])
//listing HTML
{
allUsers.map((ls,index) => (
<tr key={ls.id}>
<td>{ls.id}</td>
<td>{ls.name}</td>
<td>{ls.email}</td>
<td>
{ls.status =="ACTIVE" ? <Badge color="success" pill>Active</Badge>:<Badge color="danger" pill>Inactive</Badge>}</td>
<td>
{ls.roles.map((role) => (
role.title+" "
))}
</td>
<td><Moment fromNow ago>{ls.created_at}</Moment> </td>
<td>
<Button variant="warning" size="sm" onClick={handleShow} >Edit</Button>{' '}
<Button
onClick={e =>
window.confirm("Are you sure you wish to delete this user?") &&
deleteUser(ls.id)
}
variant="danger"
size="sm">Delete</Button>
</td>
</tr>
))
}
create.js
import {Modal, Button, Form,Dropdown} from "react-bootstrap";
import propTypes from "prop-types";
import React, {useState} from "react";
import Multiselect from 'multiselect-react-dropdown';
import { saveUser } from 'services/userService';
import {useDispatch,useSelector} from 'react-redux';
import { unwrapResult } from '#reduxjs/toolkit';
import Notify from "components/Common/Notify";
function Create({handleClose,show,roles}) {
const [selectedRoles, setSelectedRoles] = useState([]);
const dispatch = useDispatch();
const [name, setName] = useState('');
const [email, setEmail] = useState('');
const [password, setPassword] = useState('');
const [errors, setErrors] = useState([]);
function onSelectRoles(selectedList, selectedItem) {
selectedRoles.push(selectedItem.id)
}
function onRemoveRole(selectedList, removedItem) {
var index = selectedRoles.indexOf(removedItem.id)
selectedRoles.splice(index, 1);
}
const message = useSelector(state => state.user.message);
const status = useSelector(state => state.user.status);
function onSubmit(e){
e.preventDefault();
let data ={
name:name,
email:email,
password:password,
roles:selectedRoles,
}
dispatch(
saveUser(data))
.then(unwrapResult)
.then((obj) => {
if(obj.errors){
setErrors(obj.errors);
}else{
setErrors([]);
handleClose();
}
}
)
.catch((obj) => {
console.log({objErr: obj})
})
}
return (
<Modal show={show} onHide={handleClose}>
<Modal.Header closeButton>
<Modal.Title>New User</Modal.Title>
</Modal.Header>
<Modal.Body>
{status && message && (
<Notify status={status} message={message}/>
)}
<Form onSubmit={onSubmit} >
<Form.Group className="mb-3">
<Form.Label>Name</Form.Label>
<Form.Control className={errors['name'] ? "is-invalid" : ""} type="text" onChange={e => setName(e.target.value) } placeholder="Enter Name" />
{errors['name'] ?
<Form.Text className="text-danger">
{errors['name']}
</Form.Text>
:''
}
</Form.Group>
<Form.Group className="mb-3" controlId="formBasicEmail">
<Form.Label>Email address</Form.Label>
<Form.Control className={errors['email'] ? "is-invalid" : ""} type="email" onChange={e => setEmail(e.target.value) } placeholder="Enter email" />
{errors['email'] ?
<Form.Text className="text-danger">
{errors['email']}
</Form.Text>
:''
}
</Form.Group>
<Form.Group>
<Form.Label>Select Role</Form.Label>
<Multiselect
options={roles}
// selectedValues={selectedValue}
onSelect={onSelectRoles}
onRemove={onRemoveRole}
displayValue="name"
className={errors['roles'] ? "is-invalid" : ""}
/>
{errors['roles'] ?
<Form.Text className="text-danger">
{errors['roles']}
</Form.Text>
:''
}
</Form.Group>
<Form.Group>
</Form.Group>
<Form.Group className="mb-3" controlId="formBasicPassword">
<Form.Label>Password</Form.Label>
<Form.Control className={errors['password'] ? "is-invalid" : ""} type="password" onChange={e => setPassword(e.target.value)} placeholder="Password" />
{errors['password'] ?
<Form.Text className="text-danger">
{errors['password']}
</Form.Text>
:''
}
</Form.Group>
<Button variant="success" size="sm" type="submit">
Create
</Button>
</Form>
</Modal.Body>
</Modal>
);
}
Create.prototype= {
handleClose: propTypes.func.isRequired,
show: propTypes.bool.isRequired,
roles: propTypes.array.isRequired
}
export default Create;
when i add new user by using saveUser createEntityAdapter, not getting relational data "role" & getting error
i found the problem in my code, actually createEntityAdpter addone works looks like below
Adapter.addOne(state, payload.data);
i was passing only id in addOne function, as below
[saveUser.fulfilled]: (state, { payload }) => {
state.loading = false,
state.status = HTTP_STATUS.FULFILLED
if(!payload.errors){
userAdapter.addOne(state, payload.id), //wrong approach
state.message = payload.message
}
it should be pass full object in addOne function of createEntityAdapter
[saveUser.fulfilled]: (state, { payload }) => {
state.loading = false,
state.status = HTTP_STATUS.FULFILLED
if(!payload.errors){
userAdapter.addOne(state, payload.user),
state.message = payload.message
}
Now, this will work fine. now i am getting all relational data too in response.

Return errors in server side validation with Laravel and Vue

I'm trying to return the errors in server side validation so the user can know which error they have, but I don't know how to return something that it is understandable for a normal person.
Here's my front-end
<v-form>
<v-row>
<v-col cols="12" sm="6" md="6">
<v-text-field label="Serial Number" v-model="plane.serial_number" color="black" counter="30"></v-text-field>
</v-col>
</v-row>
<v-btn color="yellow" class="black-text" #click="add()">Submit</v-btn>
</v-form>
<script>
import Swal from 'sweetalert2'
export default {
data() {
return {
errors: [],
plane: {
serial_number: '',
},
}
},
methods: {
add() {
const params = {
serial_number: this.plane.serial_number,
};
axios.post(`/planes`, params)
.then(res => {
Swal.fire({
title: 'Success!',
html: 'Plane created successfully!',
icon: 'success',
confirmButtonText: 'OK',
})
}).catch(e => {
this.errors = e;
console.log(this.errors);
Swal.fire({
title: 'Error!',
icon: 'error',
})
})
},
}
}
</script>
Back-end
public function store(Request $request)
{
$this->validate($request, [
'serial_number' => ['required','string', 'unique:airplanes']
]);
$airplane = new Airplane();
$airplane->serial_number = $request->serial_number;
$airplane->save();
}
The console.log isn't returning anything at all.
In this.errors if you output this.errors.message you should see a friendly message. Hope that helps! ... You can also dig into the this.errors.response object which has things like the headers and status.

Trying to upload an image using laravel and vuejs

I have my upload html form like this
<div class="album_single_data settings_data">
<div class="album_single_img">
<figure class="thumbnail thumbnail-rounded">
<img class="main-profile" :src="getprofilepicture()" alt="">
</figure>
</div>
<div class="album_single_text">
<div class="album_btn profile_image">
<div class="btn btn-primary">
<input class="settings-file-upload" type="file" #change="updateProfilePic" ref="file" accept="image/*">
<div class="settings-file-icon">
<span class="material-icons">camera_alt</span>
Upload Profile Picture. (Note: Must Be Less Than 2MB)
</div>
</div>
</div>
</div>
</div>
<div class="form-group">
<button #click="updateInfo" class="btn btn-primary">Update Profile</button>
</div>
This is the vuejs code that handles the form submit/upload method which means anytime i click on the upload button the image uploads. but the problem is that it does not submit
export default {
name: 'Settings',
components: {
//
},
data() {
return{
form: new Form ({
id: '',
username:'',
email: '',
password: '',
name: '',
bio: '',
twitter_handle: '',
facebook_handle: '',
instagram_handle: '',
backgroundPicture: ''
}),
pic: ({
profilePicture: '',
})
}
},
created(){
axios.get("profile")
.then(({ data })=>(this.form.fill(data)))
.then(()=>(this.pic.data))
;
},
methods: {
getprofilepicture()
{
//default avatar pic if there is no photo of user
let profilePicture = "http://localhost:8000/img/profile/user.png";
//returns the current path of the
if (this.pic.profilePicture) {
if (this.pic.profilePicture.indexOf('base64') != -1) {
profilePicture = this.pic.profilePicture;
} else {
profilePicture = 'http://localhost:8000/img/profile/' + this.pic.profilePicture;
}
return profilePicture;
}
return profilePicture;
//let profilePicture = (this.form.profilePicture.length > 200) ? this.form.profilePicture : "http://localhost:8000/img/profile/"+ this.form.profilePicture ;
//return profilePicture;
},
// getBackgroundPic(){
// let backgroundPicture = "http://localhost:8000/img/profile/background.jpg";
// if(this.form.backgroundPicture){
// if(this.form.backgroundPicture.indexOf('base64') != -1){
// backgroundPicture = this.form.backgroundPicture;
// }else {
// backgroundPicture = 'http://localhost:8000/img/profile/'+ this.form.backgroundPicture;
// }
// return backgroundPicture;
// }
// return backgroundPicture;
// },
updateInfo(){
this.$Progress.start();
this.form.put('profile')
.then(()=> {
this.$Progress.finish();
this.$router.go('/profile')
})
.catch(()=>{
this.$Progress.fail()
})
},
updateProfilePic(e){
let file = e.target.files[0];
//console.log(file);
let reader = new FileReader();
if(file['size'] < 2097152){
reader.onloadend = () => {
//console.log('RESULT', reader.result)
this.pic.profilePicture = reader.result;
}
reader.readAsDataURL(file);
}else{
Toast.fire({
icon: 'error',
title: 'Ooops...',
text: 'The file you are trying to upload is more than 2MB',
})
}
},
updateBackgroundPic(e){
let file = e.target.files[0];
//console.log(file);
let reader = new FileReader();
if(file['size'] < 2097152){
reader.onloadend = () => {
this.form.backgroundPicture = reader.result;
}
reader.readAsDataURL(file);
}else{
Toast.fire({
icon: 'error',
title: 'Ooops...',
text: 'The file you are trying to upload is more than 2MB'
})
}
}
}
}
</script>
Anytime i click on the submit button i have this error message: "Undefined offset: 1", exception: "ErrorException",…}
exception: "ErrorException"
and i really do not know the cause of this error.
Below is the PHP Code that handles the server side part of the upload
public function updateProfile(Request $request)
{
$user = auth('api')->user();
$this->validate($request,[
'username' => 'required|string|max:255|unique:users,username,'.$user->id,
'name' => 'max:255',
'email' => 'required|string|email|max:255|unique:users,email,
'.$user->id,
'password' => 'sometimes|required|min:8'
]);
$currentProfilePicture = $user->profilePicture;
if($request->profilePicture != $currentProfilePicture){
$name = time().'.' . explode('/', explode(':', substr($request->profilePicture, 0, strpos($request->profilePicture, ';')))[1])[1];
Image::make($request->profilePicture)->save(public_path('img/profile/').$name);
$request->merge(['profilePicture' => $name]);
$userPhoto = public_path('img/profile/').$currentProfilePicture;
if(file_exists($userPhoto)){
#unlink($userPhoto);
}
}
$user->update($request->all());
}

Select Box is not changing immediately after changing input in ElementUi Vue

I have made a CRUD based admin pannel with laravue. Now my problem is that whenever I am on the update page, I can't change the category immediately. I always have to make change in some other field to view the changed category. Its working fine on add card page when all the fields are empty.
This is the video of my issue
https://thisisntmyid.tumblr.com/post/189075383873/my-issue-with-elementui-and-laravue-and-vue
I've included the code for my list page as well as the add/update page.
Code for the listing page that will lead u to edit page
<div class="app-container">
<h1>My Cards</h1>
<Pagination
:total="totalCards"
layout="total, prev, pager, next"
:limit="10"
:page.sync="currentPage"
#pagination="loadNewPage"
></Pagination>
<el-table v-loading="loadingCardsList" :data="cards" stripe style="width: 100%">
<el-table-column prop="name" sortable label="Product Name"></el-table-column>
<el-table-column prop="description" label="Description" width="200px"></el-table-column>
<el-table-column prop="price" label="Price"></el-table-column>
<el-table-column prop="cardcategory" sortable label="Category"></el-table-column>
<el-table-column label="Operations" width="300px">
<template slot-scope="scope">
<el-button size="mini" type="primary" #click="handleView(scope.$index, scope.row)">View</el-button>
<el-button size="mini" #click="handleEdit(scope.$index, scope.row)">Edit</el-button>
<el-button size="mini" type="danger" #click="handleDelete(scope.$index, scope.row)">Delete</el-button>
</template>
</el-table-column>
</el-table>
<el-dialog :visible.sync="viewCard" width="30%">
<el-card class="box-card">
<h1>{{currentViewedCard.name}}</h1>
<p>{{currentViewedCard.description}}</p>
<p>{{currentViewedCard.price}}</p>
<el-tag>{{currentViewedCard.cardcategory}}</el-tag>
</el-card>
</el-dialog>
</div>
</template>
<script>
import Resource from '#/api/resource';
import Pagination from '#/components/Pagination/index.vue';
const cardcategoryResource = new Resource('cardcategories');
const cardResource = new Resource('cards');
export default {
name: 'Cards',
components: {
Pagination,
},
data() {
return {
cards: [],
categories: [],
currentPage: '',
totalCards: '',
loadingCardsList: true,
currentViewedCard: '',
viewCard: false,
};
},
created() {
this.getCardCategories();
this.getCardList({ page: 1 });
},
methods: {
async getCardList(query) {
this.loadingCardsList = true;
const data = await cardResource.list(query);
this.cards = data.data;
for (const card of this.cards) {
card['cardcategory'] = this.getCategoryName(card.cardCategory_id);
}
console.log(this.cards);
this.totalCards = data.total;
this.loadingCardsList = false;
},
async getCardCategories() {
this.categories = await cardcategoryResource.list({});
console.log(this.categories);
},
loadNewPage(val) {
this.getCardList({ page: val.page });
},
getCategoryName(id) {
return this.categories[id - 1].name;
},
handleView(index, info) {
this.viewCard = true;
this.currentViewedCard = info;
},
handleEdit(index, info) {
this.$router.push('/cards/edit/' + info.id);
},
closeDialog() {
this.viewProduct = false;
this.currentProductInfo = null;
},
handleDelete(index, info) {
cardResource.destroy(info.id).then(response => {
this.$message({
message: 'Card Deleted Successfully',
type: 'success',
duration: 3000,
});
this.getCardList({ page: this.currentPage });
});
},
},
};
</script>
<style lang="scss" scoped>
</style>
Code for the add/update page
<template>
<div class="app-container">
<el-form ref="form" :model="formData" label-width="120px">
<el-form-item label="Name">
<el-input v-model="formData.name"></el-input>
</el-form-item>
<el-form-item label="Description">
<el-input type="textarea" v-model="formData.description"></el-input>
</el-form-item>
<el-form-item label="Price">
<el-input v-model="formData.price"></el-input>
</el-form-item>
<el-form-item label="Category">
<!-- DO something here like binding category id to category name sort of meh... -->
<el-select v-model="formData.cardcategory" placeholder="please select category">
<el-option v-for="item in categories" :key="item" :label="item" :value="item"></el-option>
</el-select>
</el-form-item>
<el-form-item>
<el-button type="primary" #click="editable ? updateProduct() : createProduct()">Save</el-button>
<el-button #click="editable ? populateFormData($route.params.id) : formDataReset()">Reset</el-button>
</el-form-item>
</el-form>
</div>
</template>
<script>
import Resource from '#/api/resource';
const cardcategoryResource = new Resource('cardcategories');
const cardResource = new Resource('cards');
export default {
data() {
return {
formData: {
name: '',
description: '',
price: '',
cardcategory: '',
},
categories: [],
editable: '',
};
},
created() {
this.getCategories();
if (this.$route.params.id) {
this.editable = true;
this.populateFormData(this.$route.params.id);
} else {
this.editable = false;
}
},
methods: {
async getCategories() {
this.categories = (await cardcategoryResource.list({})).map(
cat => cat.name
);
console.log(this.categories);
},
formDataReset() {
this.formData = {
name: '',
description: '',
price: '',
cardcategory: '',
};
},
populateFormData(id) {
cardResource.get(id).then(response => {
this.formData = Object.assign({}, response);
this.formData.price = this.formData.price.toString();
this.formData.cardcategory = this.categories[
this.formData.cardCategory_id - 1
];
delete this.formData.cardCategory_id;
});
},
filterFormData(formData) {
const cardData = Object.assign({}, formData);
cardData['cardCategory_id'] =
this.categories.indexOf(cardData.cardcategory) + 1;
delete cardData.cardcategory;
return cardData;
},
createProduct() {
const cardData = this.filterFormData(this.formData);
cardResource
.store(cardData)
.then(response => {
this.$message({
message: 'New Card Added',
type: 'success',
duration: 3000,
});
this.formDataReset();
})
.catch(response => {
alert(response);
});
},
updateProduct() {
const cardData = this.filterFormData(this.formData);
cardResource.update(this.$route.params.id, cardData).then(response => {
this.$message({
message: 'Card Updated Successfully',
type: 'success',
duration: 3000,
});
this.populateFormData(this.$route.params.id);
});
},
},
};
</script>
<style>
</style>
Update
here is the git hub repo for my project
https://github.com/ThisIsntMyId/laravue-admin-pannel-demo

Resources