Display list Vue Axios with Laravel - php

I'm new to laravel, axios and vue and I used this tutorial to help make a ToDo list:
I want to tweak the basic tutorial by allowing different users to store and view their tasks. I added new user registration and login, but each user would see everyone's list, not only theirs. So I made a one to many relationship between the User and Task model and added these methods to the models:
class User extends Authenticatable
{
...
public function tasks()
{
return $this->hasMany('App\Task');
}
}
class Task extends Model
{
...
public function user()
{
return $this->belongsTo('App\User');
}
}
I updated TaskController.php and TaskList.vue to display only the active user's tasks, but now in the view no list appears and new tasks can't be added.
Here is the code for the two. Everything is the same as the tutorial, except I commented next to the parts that I added:
<?php
namespace App\Http\Controllers;
use App\Task;
use Illuminate\Http\Request;
class TaskController extends Controller
{
$user = Auth::user(); //Added by me
public function index()
{
return Task::latest()->where('user_id', $user->id)->get(); //Added by me,
//this query returns whats expected in php artisan tinker
//was previously return Task::latest()->get();
//I also tried this: return $this->user->tasks->toJSON()
}
public function store(Request $request)
{
$this->validate($request, [
'body' => 'required|max:500'
]);
return Task::create([
'body' => request('body'),
'user_id' => $user->id //Added by me
]);
}
public function destroy($id)
{
$task = Task::findOrFail($id);
$task->delete();
return 204;
}
}
In TaskList.vue
<template>
<div class='row'>
<h1>My Tasks</h1>
<h4>New Task</h4>
<form action="#" #submit.prevent="createTask()">
<div class="input-group">
<input v-model="task.body" type="text" name="body" class="form-control" autofocus>
<span class="input-group-btn">
<button type="submit" class="btn btn-primary">New Task</button>
</span>
</div>
</form>
<h4>All Tasks</h4>
<ul class="list-group">
<li v-if='list.length === 0'>There are no tasks yet!</li>
<li class="list-group-item" v-for="(task, index) in list">
{{ task.body }}
<button #click="deleteTask(task.id)" class="btn btn-danger btn-xs pull-right">Delete</button>
</li>
</ul>
</div>
</template>
<script>
export default {
data() {
return {
list: [],
task: {
id: '',
body: '',
user_id: '' ///Added by me
}
};
},
created() {
this.fetchTaskList();
},
methods: {
fetchTaskList() {
axios.get('api/tasks').then((res) => {
this.list = res.data;
});
},
createTask() {
axios.post('api/tasks', this.task)
.then((res) => {
this.task.body = '';
this.task.user_id = ''; ///added by me
this.edit = false;
this.fetchTaskList();
})
.catch((err) => console.error(err));
},
deleteTask(id) {
axios.delete('api/tasks/' + id)
.then((res) => {
this.fetchTaskList()
})
.catch((err) => console.error(err));
},
}
}
</script>
</script>
The app worked until I added the few lines mentioned above. Now nothing shows in the display and no new tasks can be added. I am new to laravel and totally new to axios and vue, but to me it seems like what I added should work. There are no error messages when I run it, it just doesn't produce what I want.

Related

Display multiple categories in product page (many to many) in laravel/vue

Please help, I am trying to display multiple categories on the product page, but I get the wrong categories. There are many to many relationships. Can not find the answer on google.
Categories table
Records table
category_record table
Product page (Vue), yellow-marked wrong category displayed
Folder tree and API routes
Categories.php
class Categories extends Model
{
public function records() {
return $this->belongsToMany(Record::class, 'category_record', 'record_id', 'categories_id')->withTimestamps();
}
}
Record.php
class Record extends Model
{
protected $fillable = [
'name', 'price', 'description', 'units', 'image', 'size', 'color'
];
public function categories() {
return $this->belongsToMany(Categories::class, 'category_record', 'record_id', 'categories_id')->withTimestamps();
}
}
RecordController.php
class RecordController extends Controller
{
public function index() {
return RecordIndexResource::collection(
Record::all()
);
}
public function show($id) {
return new RecordShowResource(Record::findOrFail($id));
}
}
RecordShowResource.php
public function toArray($request)
{
return [
'id' => $this->id,
'title' => $this->title,
'description' => $this->description,
'price' => $this->price,
'units' => $this->units,
'size' => $this->size,
'color' => $this->color,
'image' => $this->image,
];
}
Record.vue to display data:
<template>
<div class="review-page">
<div class="record-wrapper" v-if="!loading">
<div class="record-text">
<img :src="'/storage/' + record.image" :alt="record.title" />
<div class="record-title">{{ record.title }}</div>
<hr />
<div v-for="(category, index) in categories" :key="index">
<p>Categories: {{ category.name }}</p>
</div>
<br />
<p>Product Details</p>
<div class="record-description">{{ record.description }}</div>
<div class="record-details-price">€{{ record.price }}</div>
</div>
<record-options v-bind="record" />
</div>
<div class="loading" v-else></div>
</div>
</template>
<script>
import RecordOptions from "./RecordOptions.vue";
export default {
components: {
RecordOptions,
},
data() {
return {
record: null,
categories: [],
loading: false,
};
},
async created() {
this.loading = true;
await axios.get(`/api/records/${this.$route.params.id}`).then((response) => {
this.record = response.data.data;
this.loading = false;
});
axios
.get(`/api/categories/${this.$route.params.id}`)
.then((response) => {
this.categories = response.data;
})
.catch((error) => {
console.log(error);
});
},
};
</script>
please help me to find out the way.

How do I show a dynamic navigation bar on a dynamic web page in Laravel?

I have a dynamic navigation bar, created however it won't show on the dynamic web page.
The current output is:
ErrorException
Undefined variable: navContent (View: C:\Users\Computer
Angel\Documents\blog\resources\views\page\dynamic.blade.php)
The desired output is my dynamic.blade.php where the pageContent is the dynamic page content the user inputted through a form and the dynamic navigation bar in the tags.
This is my dynamic.blade.php:
<nav>
#foreach($navContent as $nav)
{!!nav-navName!!}
#endforeach
</nav>
<body>
{!!$pageContent->pageContent!!}
</body>
This is my NavController.php:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\Nav;
use DB;
use Illuminate\Database\MySqlConnection;
class NavController extends Controller
{
public function index()
{
$navs = Nav::all();
return view('navManagement', compact('navs'));
}
public function create()
{
return view('createNav');
}
public function store(Request $request)
{
$data = request()->validate([
'navName' => 'required',
'navLink' => 'required',
]);
$nav = new Nav([
'navName' => $request->get('navName'),
'navLink' => $request->get('navLink'),
]);
$nav->save();
return redirect('/n');
}
public function show($navName)
{
$navContent = DB::table('navs')->where('navName',$navName)->first();
return view('page.dynamic', ['navContent' => $navContent]);
}
public function edit($navName)
{
$navContent = DB::table('navs')->where('navName',$navName)->first();
return view('editNav', ['navContent' => $navContent]);
}
public function update(Request $request)
{
$data = $request->validate([
'navName' => 'required|exists:navs,navName',
'navLink' => 'required'
]);
$obj = \App\Nav::where('navName', $request->navName)
->update([
'navLink' => $request->navLink
]);
return redirect('/n');
}
public function destroy(Request $request)
{
$obj = \App\Nav::where('navName', $request->navName)
->delete();
return redirect('/n');
}
}
This is my PageController.php:
<?php
namespace App\Http\Controllers;
use App\Page;
use Illuminate\Http\Request;
use DB;
use Illuminate\Database\MySqlConnection;
class PageController extends Controller
{
public function index()
{
$pages = Page::all();
return view('pageManagement', compact('pages'));
}
public function create()
{
//This will load create.blade.php
return view('createPage');
}
public function store(Request $request)
{
$data = request()->validate([
'title' => 'required',
'URI' => 'required|min:5|max:10|',
'pageContent' => 'required',
]);
$page = new Page([
'title' => $request->get('title'),
'URI' => $request->get('URI'),
'pageContent' => $request->get('pageContent'),
]);
$page->save();
return redirect('/p');
}
public function show($URI)
{
$pageContent = DB::table('pages')->where('URI',$URI)->first();
return view('page.dynamic', ['pageContent' => $pageContent]);
}
public function edit($URI)
{
$pageContent = DB::table('pages')->where('URI',$URI)->first();
return view('editPage', ['pageContent' => $pageContent]);
}
public function update(Request $request)
{
$data = $request->validate([
'title' => 'required',
'URI' => 'required|min:5|max:10|exists:pages,URI',
'pageContent' => 'required'
]);
$obj = \App\Page::where('URI', $request->URI)
->update([
'title' => $request->title,
'pageContent' => $request->pageContent
]);
return redirect('/p');
}
public function destroy(Request $request)
{
$obj = \App\Page::where('URI', $request->URI)
->delete();
return redirect('/p');
}
}
This is my Nav.php:
class Nav extends Model
{
protected $fillable = ['navName', 'navLink'];
}
This is my Page.php:
class Page extends Model
{
protected $fillable = ['title', 'URI', 'pageContent'];
}
This is my migration for pages:
public function up()
{
Schema::create('pages', function (Blueprint $table) {
$table->id();
$table->string('title');
$table->string('URI');
$table->text('pageContent');
$table->timestamps();
});
}
This is my migration for nav:
public function up()
{
Schema::create('navs', function (Blueprint $table) {
$table->id();
$table->string('navName');
$table->string('navLink');
$table->timestamps();
});
}
This is my createNav.blade.php:
<form action="/storeNav" method="post">
#csrf
<label for="navName">Navigation Bar Option Name:</label><br>
<input type="text" id="navName" name="navName" autocomplete="off" value="{{ old('navName') }}">
<br>
#error('navName') <p style="color: red">{{ $message }}</p> #enderror
<label for="navLink">Navigation Bar Option Link:</label><br>
<input type="text" id="navLink" name="navLink" autocomplete="off" value="{{ old('navLink') }}">
<br>
#error('navLink') <p style="color: red">{{ $message }}</p> #enderror
<input type="submit" value="Submit">
</form>
This is my createPage.blade.php:
<form action="/storePage" method="post">
#csrf
<label for="title">Title:</label><br>
<input type="text" id="title" name="title" autocomplete="off" value="{{ old('title') }}"><br>
#error('title') <p style="color: red">{{ $message }}</p> #enderror
<label for="URI">URI:</label><br>
<input type="text" id="URI" name="URI" autocomplete="off" value="{{ old('URI') }}"><br>
#error('URI') <p style="color: red">{{ $message }}</p> #enderror
<label for="pageContent">Page Content:</label><br>
<textarea id="pageContent" name="pageContent" value="{{ old('pageContent') }}"></textarea>
#error('pageContent') <p style="color: red">{{ $message }}</p> #enderror
<input type="submit" value="Submit">
</form>
This is my web.php:
Route::get('/page/{URI}', 'PageController#show');
Route::get('/page/{URI}/edit', 'PageController#edit');
Route::get('/p', 'PageController#index');
Route::get('/createPage', 'PageController#create');
Route::post('/storePage', 'PageController#store');
Route::patch('/page/{URI}', 'PageController#update');
Route::delete('/page/{URI}', 'PageController#destroy');
Route::get('/nav/{navName}/edit', 'NavController#edit');
Route::get('/n', 'NavController#index');
Route::get('/createNav', 'NavController#create');
Route::post('/storeNav', 'NavController#store');
Route::patch('/nav/{navName}', 'NavController#update');
Route::delete('/nav/{navName}', 'NavController#destroy');
Below is my github repository link, if you want to take a look at my full code, or you want to try run the code in your Integrated Development Environment.
https://github.com/xiaoheixi/blog
Thanks for reading! :D
If is complaining that it can't find a variable called $navContent.
I can't see you passing it to either of the views you are calling from your index() functions.
return view('navManagement', compact('navs'));
return view('pageManagement', compact('pages'));
You would need to set that varaible and pass it to the view
// Get the nav content however you want, this is just a crude example
$navContent = $this->getMyNavContent();
return view('navManagement', [
'navs' => $navs,
'navContent' => $navContent
]);
I'm guessing you want to find a way to embed the dynamic nav without having to add the navContent every time you render a view, as that's what the other answer is suggesting. You could achieve this using a middleware, say dynamicNav and registering your routes under that middleware group.
In that middleware you can do all the logic of fetching the nav content and then use something like merge, as shown here:
$request->merge(['dynamicNav' => $navContent]);
This way your middleware will add the data to every request which goes through it, although I wouldn't recommend this solution.
What I would do is cache the nav content and retrieve in the view using the cache() helper, then override the save() method of the model to also update the cache when the DB is updated (to avoid duplicate code, you could create a trait for the fetching of the nav). Example:
// in your model
public function save(array $options = [])
{
Cache::put('nav-content', getNavContent());
parent::save();
}

Passing multiple variable with axios to controller laravel

I'm trying to insert a lecture id a students table. I need to pass the student's id as well as the lecture's to the controller. I'm using axios to post 2 parameters to the controller. My codes not working, did i do it wrong? New in Laravel. thanks
Vue Component
<i class="fas fa-user-plus"></i>
<script>
export default {
data () {
return {
student:'',
lecture_id:this.$route.params.id,
}
},
methods:{
setLectureFK($student_id){
axios.post('/api/internship/setLecture/'+$lecture_id,'/'+$student_id);
}
},
}
Controller
public function setLecture($lecture,$student)
{
$student = student::findOrFail($student);
$student->lecture_id_FK = $lecture;
$student->save();
}
API.PHP
Route::post('internship/setLecture/{lecture}/{student}', 'API\InternshipController#setLecture')->name('internship.setLecture');
As far as I can see there is the syntax error in your vue component .
In this line
axios.post('/api/internship/setLecture/'+$lecture_id,'/'+$student_id);
You have put the comma instead of + it should be like this
axios.post('/api/internship/setLecture/'+$lecture_id+'/'+$student_id);
Try this:
Vue Component
<i class="fas fa-user-plus"></i>
<script>
export default {
data () {
return {
student:'',
lecture_id:this.$route.params.id,
}
},
methods:{
setLectureFK(student_id){
axios.post('/api/internship/setLecture',{student_id:student_id,lecture_id:this.lecture_id});
}
},
}
Controller
public function setLecture(Request $request)
{
$student = student::findOrFail($request->student_id);
$student->lecture_id_FK = $request->lecture_id;
$student->save();
}
api.php
Route::post('internship/setLecture', 'API\InternshipController#setLecture')->name('internship.setLecture');

How to associate files to post with Laravel 5.6

I am using Laravel for my web app and I want to associate files to my posts in indepent way with his own form, but I have some problems
My routes (I am using a auth control package, but actually I am admin):
Route::post('file', 'fileController#store')->name('file.store')
->middleware('permission:file.create');
Route::get('file', 'fileController#index')->name('file.index')
->middleware('permission:file.index');
Route::get('file/create/', 'fileController#create')->name('file.create')
->middleware('permission:file.create');
Route::put('file/{id}', 'fileController#update')->name('file.update')
->middleware('permission:file.edit');
Route::get('file/{id}', 'fileController#show')->name('file.show')
->middleware('permission:file.show');
Route::delete('file/{id}', 'fileController#destroy')->name('file.destroy')
->middleware('permission:file.destroy');
Route::get('file/{id}/edit', 'fileController#edit')->name('file.edit')
->middleware('permission:file.edit');
Route::get('download/{filename}', 'fileController#download')->name('file.download')
->middleware('permission:file.download');
My migration:
Schema::create('files', function (Blueprint $table) {
$table->increments('id');
$table->integer('user_id')->unsigned();
$table->integer('files_id')->unsigned();
$table->string('filenames');
$table->integer('fileable_id')->unsigned();
$table->string('fileable_type');
$table->timestamps();
});
My File Model:
class File extends Model
{
protected $fillable = [
'filenames', 'project_id'
];
public function user()
{
return $this->belongsTo(User::class);
}
My Project Model:
public function files()
{
return $this->morphMany(File::class, 'fileable')->whereNull('files_id');
}
My Controller to store:
class FileController extends Controller
{
public function store(Request $request)
{
$this->validate($request, [
'filenames' => 'required',
'project_id' => 'required',
// 'filenames.*' => 'mimes:doc,pdf,docx,zip'
]);
if($request->hasfile('filenames'))
{
foreach($request->file('filenames') as $file)
{
$name=$file->getClientOriginalName();
$file->move(public_path().'/files/', $name);
$data[] = $name;
}
}
$file= new File();
$file->filenames = $request->get('filenames');
$file->filenames= $name;
$file->user()->associate($request->user());
$project = Project::findOrFail($request->get('project_id'));
$project->files()->save($file);
$file->save();
return back();
}
public function download( $filename = '' ) {
// Check if file exists in storage directory
$file_path = public_path() . '/files/' . $filename;
if ( file_exists( $file_path ) ) {
// Send Download
return \Response::download( $file_path, $filename );
} else {
return back()->with('info', 'Archivo no existe en el servidor');
}
}
The Form in blade:
<form method="post" action="{{ route('file.store') }}" enctype="multipart/form-data">
<div class="input-group hdtuto control-group lst increment" >
<input type="file" name="filenames[]" class="myfrm form-control">
<input type="hidden" name="project_id" value="{{ $project->id }}" />
<div class="input-group-btn">
<button class="btn btn-success" type="button"><i class="fldemo glyphicon glyphicon-plus"></i>Add</button>
</div>
</div>
<button type="submit" class="btn btn-success" style="margin-top:10px">Submit</button>
</form>
Foreach to download files:
#foreach($project->files as $file)
<li>{{ $file->user->name }}: <a href="{{ url('/download/')}}/{{$file->filenames}}" download> {{$file->filenames}}</a></li>
#endforeach
I send files from Project Controll
The reason you are getting the first error message is because the Project with the id you get from Request is not found in the Database and returns null instead of an object. That would mean you are indeed calling files() method on null. To resolve this there are multiple steps.
1.) Make sure project_id is inside the Request at all times:
$this->validate($request, [
'filenames' => 'required',
'project_id' => 'required',
// 'filenames.*' => 'mimes:doc,pdf,docx,zip'
]);
2.) Make sure to check for project if it exists after retrieving it from database, this can be done in two ways.
a) You can either find the project or throw an Exception if it's not found:
$project = Project::findOrFail($request->get('project_id');`
b) You can check with a simple if statement if it does not exist and do something
$project = Project::find($request->get('project_id');
if (!$project) {
// Project not found in database
// Handle it
}

Updating database with laravel

Let me explain situation, person is searching through skills and when clicked displays list of handymans with that skill, when user clicks on one of them, full details are displayed. user then clicks assign job link and is taken to a page with jobs along with checkbox and when desired job is chosen, and submit button clicked, I want a database to update "job_id" value in "handymen" database. How could that be done?
#extends('layouts.master')
#section('title', 'Assign Job')
#section('content')
#section('content')
<form action="{{url('assignjob')}}" method="POST">
{{ csrf_field() }}
#foreach ($jobs as $job)
<div>
<label>{{$job->name}}</label>
<input type='checkbox' value='{{$job->id}}' name='jobs[]'/>
</div>
#endforeach
<input type="submit" name="submitBtn" value="Assign Job">
</form>
#endsection
function search()
{
$skills = Skill::all();
return view('layouts/search',['skills' => $skills]);
}
function details($skillId)
{
$skill = Skill::find($skillId);
$handymen = $skill->handymen;
return view('layouts/details', ['skill' => $skill,'handymen' => $handymen]);
}
function assignJob($handymanId)
{
$assignJob = Hadnyman::find($handymanId);
$jobs = Job::all();
return view('layouts/assignjob',['jobs' => $jobs]);
}
function jobassign(Request $request)
{
return redirect('assignjob');
}
function skilledHandyman($handymanId)
{
$skilledHandyman = Handyman::find($handymanId);
return view('layouts/skilledHandyman', ['skilledHandyman' => $skilledHandyman]);
}
If a specific code is needed, please let me know
You should look at Eloquent Relationship.
Handymen has many Job
class Handymen extends Model {
...
public function jobs() {
return $this->hasMany(App\Job::class);
}
}
In your controller
function assignJob(Request $request, $id)
{
$handymen = Handyman::findOrFail($id);
// $request->get('jobs') = [1, 6, 7, etc...]
$handymen->saveMany($request->get('jobs'));
return ...;
}

Categories