I am creating a web app having dashboard using laravel and vue.
When I pass data from controller to vue file data is received properly but when I set it to vue variable the value is not set in the variable. All data is received and its displayed in the console but when I set it to the vue variable, the variable doesn't update its value.
This is my Controller class:
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use App\User;
class UsersController extends Controller
{
//
public function index()
{
$users=User::all();
return response()->json($users);
}
}
This is myTeam.vue for receiving and displaying the data:
<template>
<div class="container">
<div class="row justify-content-center">
<div class="col-md-8">
<div class="card card-default">
<div class="card-header">Example Component</div>
<h1>
This request list
Hello,{{this.items}}
</h1>
<ul class="list-group">
<li class="list-group-item" v-for="t in items">{{items}}</li>
</ul>
</div>
</div>
</div>
</div>
</template>
<script>
export default {
data(){
return {
//items: []
items:[],
}
},
created() {
var self=this;
axios.get('/allusers').then((response) => self.items=response.data) .catch((error)=>console.log(error));
axios.get('/allusers') .then(response => console.log(response.data));
console.log('Component mounted.'+this.items)
},
}
</script>
Now when I run it the console prints the array properly means data is received but when I set it to items variable the data is not set.
My Output is this:
This is the output image file
Please check it and thanks in advance ...
This is never print items array because it's execute before the ajax response is filled.
console.log('Component mounted.'+this.items)
That's why your console is always blank. You can search about blocking and non blocking programming.
your code have small bug. Update your code and try this:
<h1>
This request list
Hello,{{items}}
</h1>
<ul class="list-group">
<li class="list-group-item" v-for="t in items">{{t}}</li>
</ul>
...
<script>
export default {
data(){
return {
items:[],
}
},
mounted: function () {
this.getList();
}
methods: {
let _this = this;
axios.get('/allusers')
.then((response) => _this.items = response.data)
.catch((error)=>console.log(error));
},
}
</script>
This can help you. Good luck.
Related
I have created a blade layout that uses #yeild and has a script to get some json data, this looks like this:
...
<div class="col-lg-6" id="comments">
<h3>Comments</h3>
#yield("comment_list")
</div>
...
<script>
const Comments = {
data() {
return {
comments: []
}
},
mounted() {
axios.get("{{route('api.comments.index')}}")
.then(response=> {
this.comments = response.data;
})
.catch(response => {
console.log(response);
})
}
}
Vue.createApp(Comments).mount('#comments');
</script>
Then I add to the "comment_list" in a different file.
I know I can loop through the response like this:
<li v-for="comment in comments">
#{{ comment.title }}
</li>
However I need this in a custom blade component, an example of what I want to achieve is this:
#foreach($comment in comments)
<x-comment-view :title="$comment->title" :content="$comment->content" :author="$comment->user->name"/>
#endforeach
Any help would be appreciated, I'm not sure what to do here.
I am building a Laravel app and trying to use vue.js (without much success!). I'm not understanding the way components work with ajax data. Almost all examples I've found showing this functionality define the data for the component at the app level, not the component level.
I'm trying to dynamically define my data in the component itself, and always get the error that Property or method tasks is not defined on the instance but referenced during render. Here's the component, which is meant to just call out to an endpoint to pull basic "to do" tasks:
Vue.component('tasks', {
data: function() {
return {
tasks: []
}
},
mounted() {
this.getTasks();
},
methods: {
getTasks() {
axios.get('/tasks').then(function (response) {
this.tasks = response.data;
console.dir(this.tasks);
})
.catch(function (error) {
console.log(error);
});
}
},
template: `
<div class="card">
<div class="card-title">{{ task.name }}</div>
<div class="card-body">
<div class="service-desc">{{ task.description }}</div>
<div class="task-notes"><input class="form-control" v-model="task.notes" placeholder="Notes"></div>
<div class="task-active"><input type="checkbox" checked data-toggle="toggle" data-size="sm" v-model="task.active" v-on:click="$emit('disable')"></div>
</div>
</div>
`
});
the component is called from within the blade template using:
<tasks v-for="task in tasks" :key="task.id"></tasks>
tasks is declared in the data function, so I'm not sure why vue is telling me it's not defined?
When you define a data property on a component it's only available within that component and its template. Your v-for directive is in the parent scope (i.e outside of the component where tasks is defined).
The simplest solution here is probably to move the container element inside the component, and iterate over the tasks there:
<div>
<div class="card" v-for="task in tasks" :key="task.id">
<div class="card-title">{{ task.name }}</div>
<div class="card-body">
<div class="service-desc">{{ task.description }}</div>
<div class="task-notes"><input class="form-control" v-model="task.notes" placeholder="Notes"></div>
<div class="task-active"><input type="checkbox" checked data-toggle="toggle" data-size="sm" v-model="task.active" v-on:click="$emit('disable')"></div>
</div>
</div>
</div>
Note: you can't use v-for a template's root element, which is why you'd move the container element into the template.
An alternative is break this into two components (e.g. TaskList and TaskItem) where the parent component is responsible for fetching the tasks from the API. The child component can just receive a single task as a prop and render it to the UI.
TaskList
Vue.component('task-list', {
data: function() {
return {
tasks: []
}
},
mounted() {
this.getTasks();
},
methods: {
getTasks() {
axios.get('/tasks').then(response => {
this.tasks = response.data;
console.dir(this.tasks);
})
.catch(error => {
console.log(error);
});
}
},
template: `
<div class="container">
<task-item
v-for="task in tasks"
:key="task.id"
:task="task"
/>
</div>
`
});
TaskItem
Vue.component('tasks', {
props: {
task: {
required: true
}
},
template: `
<div class="card">
<div class="card-title">{{ task.name }}</div>
<div class="card-body">
<div class="service-desc">{{ task.description }}</div>
<div class="task-notes"><input class="form-control" v-model="task.notes" placeholder="Notes"></div>
<div class="task-active"><input type="checkbox" checked data-toggle="toggle" data-size="sm" v-model="task.active" v-on:click="$emit('disable')"></div>
</div>
</div>
`
});
The advantage of this is that it separates the responsibility of the components a little better. You could add logic to the TaskList component to handle displaying a loading spinner and/or error messages for the API call, while TaskItem only has to concern itself with displaying a single task.
I am using Laravel 5.6 and create model named process and a controller with a function that gets all the records of the model:
public function showProcessList(){
return response()->json(Process::all());
}
In the web.php routes file also defined the route to retrieve the records, it works well, i tested the endpoint and i can see the data:
Route::get('process/list', 'ProcessController#showProcessList');
In a blade file i try to show the list creating a Vue component like this:
<!-- Process List -->
<div class="row">
<process></process>
</div>
<script src='{{ asset("public/js/app.js") }}'></script>
file app.js has this:
window.Vue = require('vue');
/**
* Next, we will create a fresh Vue application instance and attach it to
* the page. Then, you may begin adding components to this application
* or customize the JavaScript scaffolding to fit your unique needs.
*/
Vue.component('process', require('./components/Process.vue'));
const app = new Vue({
el: '#app'
});
components/Process.vue contains this:
<template>
<div class="tile mb-4 col-md-6 col-lg-12" id="listProcess">
<div class="page-header">
<h3 class="mb-4 line-head">Process List</h3>
</div>
<div v-for="process in processList">
<p>{{ process.name }}</p>
</div>
</div>
</template>
<script>
import axios from 'axios';
export default {
data () {
return {
processList: [],
}
},
created() {
this.showProcessList();
},
methods: {
showProcessList () {
axios.get('/process/list')
.then(response => {
this.processList = response.body;
});
}
},
}
</script>
Then execute npm run dev and load in web browser the view that invoke the Vue component:
<div class="row">
<process></process>
</div>
<script src='{{ asset("public/js/app.js") }}'></script>
(I have to add public folder to the path of css and js files)
nothing happens, the data doesn't load in the view and i cannot see any error in console.
Testing the endpoint the result is:
[
{
"id": 1,
"created_at": "2018-03-28 04:33:02",
"updated_at": "2018-03-28 04:33:02",
"name": "first_process",
},
]
So, at this point i cannot see where is the error in my code or what i missing?
Thanks.
I have two methods show and index I have a list of items on the index method that when a user clicks it takes her to another page containing some data that belongs to that id. Instead of doing it such way, I want to use jquery to make the data load on the same page. I have the following on my index.blade.php view. How do I achieve this in laravel?
#foreach ($categories as $category)
<div class="body">
<h4><a style="text-decoration: none; " href="{{ URL::route('category.show', $category->id) }}">{{$category->name}}</a></h4>
</div>
#endforeach
<?php
namespace App\Http\Controllers;
use Illuminate\Http\Request;
use illuminate\HttpResponse;
use App\Http\Requests\todolistRequest;
use App\Http\Requests\CreateCategoryRequest;
use App\Http\Requests;
use App\Companylist;
use App\Category;
use Illuminate\Support\Facades\DB;
class CategoryController extends Controller
{
public function create(){
return view('category.create');
}
public function index(){
$categories=Category::all();
return view('category.index',compact('categories'));
}
public function store(CreateCategoryRequest $request){
$category = new Category($request->all());
$category->save();
return \Redirect::route('category.create')->with('message', 'Your list has been created!');
}
public function show($id)
{
$category = Category::findOrFail($id)->companylist()->get();
$cat=Category::findOrFail($id);
// this my route
Route::resource('category','CategoryController');
return view('category.show')->with('category', $category)->with('cat',$cat);
}
//
}
Use bootstrap modals or pop ups.
Design your category.show view according to your needs.
Call ajax and append your returned view response to that modal body and show it so it will be exactly same view you wanted.
example code is for replace and ajax is like
This is replace modal
<!-- Show Modal content-->
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal">×</button>
<h4 class="modal-title">Show data</h4>
</div>
<div class="modal-body replace">
</div>
</div>
This will be your ajax method
$('.showModalButton').on('click',function(e){
var id = $(this).data('id'); // get id of resource you want to show
$('.replace').empty(); //
$.ajax({
url: 'your route/'+id,
type: "GET",
success:function(data) {
$('.replace').html(data);
},
error:function(jQXHR, textStatus, errorThrown) {
console.log(jQXHR);
console.log(textStatus);
console.log(errorThrown);
}
}); //end Ajax call
});
This will be your show method in controller
public function show($id)
{
$category = Category::findOrFail($id)->companylist()->get();
$cat=Category::findOrFail($id);
// this my route
Route::resource('category','CategoryController');
return view('category.show')->with('category',$category)->with('cat',$cat);
}
Design category.show however you want to show your data.
There is a simple page where i display search results by keywords.
But now i want to search on those results by some criteria.
How can i do it
SearchController
class SearchController extends \BaseController {
public function search() {
$keyword = Input::get('header-search-query');
if (empty($keyword)) {
$product = Product::paginate(10);
$this - > setModel($product);
return View::make('product.listbykeyword') - > with('products', $product);
}
return View::make('product.listbykeyword') - > with('products', Product::like('title', $keyword) - > paginate(10));
}
public function advance() {
//what should i put here
}
}
View
#foreach($products as $product)
<div class="media">
<div class="media-left" style="width:16%;">
<a href="{{ URL::to('image/'.$product->productImage()->first()['image']) }}">
{{ HTML::image('image/'.$product->productImage()->first()['image'],'no-image',array('class'=>'media-object','height'=>'100','width'=>'100'))}}
</a>
</div>
<div class="media-body">
<h4 class="media-heading">{{ HTML::link('/product/'.$product->id,$product->title) }}</h4>
<p>{{substr($product->description,0,85)}}</p>
<p>Price : {{$product->price}} TK</p>
<p class="time">{{$product->created_at->diffForHumans()}}
<b>Near</b> {{$product->location}}
</p>
</div>
</div>
<hr></hr>
#endforeach
As it was true that you can't able to use Datatables in your case as it is a public search i would recommend you to use ajax call on the keychange event.
Step 1 :
Detect the keychange from your textbox
<input id='myTextbox1' type='text'/>
$('#myTextbox1').on('input', function() {
alert('Text1 changed!');
});
Here is the fiddle
Step 2 :
Call the ajax page to your controller
$.ajax({
type: "POST",
url : "yourcontroller",
data : dataString,
success : function(data){
$("#result").html(data);
}
});
Place a div named as result in your page.
So, First time you will get the result from your default controller you use to search and then next time whenever you type the text in your myTextbox1 it will call the controller yourcontroller and in your controller you should get the datastring and return the matching output to the view.
Hope this helps you.