Need guidance on how to populate a DIV using server side Ajax query then iterate with #foreach. Currently getting 'undefined variable' error - ajax

In a Laravel project I'm attempting to use Ajax to populate a DIV and then use #foreach to populate the store gallery. If possible I wanted to use a Server side content generation strategy. However, something silly is going on that I can't figure out-- I'm getting the following error:
$user_query is undefined
Make the variable optional in the blade template. Replace {{ $user_query }} with {{ $user_query ?? '' }}
How is this (#foreach ($user_query as $item)) suppose to be constructed in the blade?
routes
Route::get('/ajaxStoreRequest', 'StoreController#ajaxStoreRequest');
Route::post('/ajaxStoreRequest/post', 'StoreController#ajaxStoreRequestPost');
Here is the StoreController.php:
<?php
namespace App\Http\Controllers;
use App\Coin;
use Illuminate\Http\Request;
use App\DataTables\StoresDataTable;
use App\DataTables\StoresDataTableEditor;
use Illuminate\Support\Facades\DB;
class StoreController extends Controller
{
public function ajaxStoreRequest()
{
return view('store.index');
}
public function ajaxStoreRequestPost(Request $request)
{
$user_query= DB::table('coins')
->select('id','year', 'mint', 'series', 'rating', 'rating_group','photo_link1', 'for_sale_price')
->where('for_sale', '=', 1)
->where('sold', '=', 0)
->where('series', '=', $request->series)
->where('year', '=', $request->year)
->where('mint', '=', $request->mint)
->where('rating_group', '=', $request->rating_group)
->get();
return response()->json($user_query);
}
}
a DD($user_query); shows the following array format
Illuminate\Support\Collection {#552
#items: array:1 [
0 => {#555
+"id": 2
+"year": 1878
+"mint": "Philadelphia"
+"series": "Morgan Dollar"
+"rating": "Ungraded"
+"rating_group": "PCGS"
+"photo_link1": "editor/20200328_002220_888888966_732020162248388.jpg"
+"for_sale_price": "44"
}
]
}
Here is the Ajax script from the bottom of the store/index.blade.php
<script type="text/javascript">
$.ajaxSetup({
beforeSend: function(xhr, type) {
if (!type.crossDomain) {
xhr.setRequestHeader('X-CSRF-Token', $('meta[name="csrf-token"]').attr('content'));
}
},
});
$(".btn-submit").click(function(e){
e.preventDefault();
var series = $("#series option:selected").val();
var year = $("input[name=year]").val();
var mint = $("#mint option:selected").val();
var rating_group = $("#rating_group option:selected").val();
var price_filter = $("input[name=price_filter]:checked").val();
$.ajax({
type:'POST',
url:'/ajaxStoreRequest/post',
data:{series:series, year:year, mint:mint, rating_group:rating_group, price_filter:price_filter},
success:function(result){
$('.collapse').collapse('show');
$('#user_query').html(result);
}
});
});
</script>
Here is the HTML further up in the store/index.blade.php
<div class="row row-deck js-gallery collapse">
<div class="user_query" id="user_query">
#foreach ($user_query as $item) <!-- THIS IS THE ERROR -->
<div class="col-md-6 col-xl-4">
<div class="block">
<div class="options-container">
#if ($item->photo_link1)
<img class="img-fluid options-item" src="storage/{{$item->photo_link1}}" style="width:300px; height:300px" alt="">
#else
<img class="img-fluid options-item" src="images/no-user-profile-picture-1200x900.jpg" style="width:300px; height:300px" alt="">
#endif
<div class="options-overlay bg-black-75">
<div class="options-overlay-content">
<a class="btn btn-sm btn-primary img-lightbox" href="gallery/{{$item->id}}">
View
</a>
<a class="btn btn-sm btn-light" href="javascript:void(0)">
<i class="fa fa-plus text-success mr-1"></i> Add to cart
</a>
</div>
</div>
</div>
<div class="block-content">
<div class="mb-2">
<div class="h4 font-w600 text-success float-right ml-1">${{$item->for_sale_price}}</div>
<a class="h4" href="be_pages_ecom_store_product.html">{{$item->year}}-{{$item->mint}}</a>
</div>
<p class="font-size-sm text-muted">{{$item->series}} ({{$item->rating}} {{$item->rating_group}})</p>
</div>
</div>
</div>
#endforeach
</div>
</div>

I'm attempting to use Ajax to populate a DIV and then use #foreach
This is fundamentally backwards. store/index.blade.php is rendered server side, so any data returned from your ajax call must be added to the DOM using JavaScript.

Related

I want to show a first category product when i reload my page using laravel?

currently when i click to any category related to product is showing perfectly but i need to show first category product when i reload my page first time Does anyone have an idea please help me thanks.
Controller
public function getproduct(Request $request)
{
$category_id = $request->data;
if ($category_id) {
$product = Product::with('productColorGallary')->whereHas('productCategory', function (Builder $query) use ($category_id) {
$query->where('mf_product_category_id', $category_id);
})->get();
} else {
$product = Product::with('productColorGallary')->get();
}
$data = [
'products' => $product
];
return response()->json($data, 200);
}
jquery script
<script>
$(document).ready(function(){
$('.productcategory').click(function () {
let url = "{{route('products.getproduct')}}";
let path = '{{config('wall_master_furishing.file_url')}}';
axios.get(url, {
params:{
data: $(this).data('id'),
}
}).then((res)=>{
let product =res.data.products;
$('#product').html("");
product.forEach(element => {
console.log(element);
$('#product').append(
`<div class="col-md-4 col-sm-6 col-6">
<div class="wallprodCard">
<div class="prodcardImage">
<img src="${path}${element.product_color_gallary.featured_image}" alt="">
<a class="prodcardFancy" href="${path}${element.product_color_gallary.featured_image}" data-fancybox="images" data-caption="Flooring">
<i class="fa fa-search-plus">
</i>
</a>
</div>
<div class="prodcardDescp">
<a href="{{url('')}}/wallpaper-details">
<h4 class="prodcardtitle">${element.name}
</h4>
</a>
<p class="text">${element.description}
</p>
</div>
</div>
</div>
`);
});
});
});
</script>

How to pass a parameter from a view to the controller with Ajax? Codeigniter

I am just learning and I would like you to help me solve this problem: I have two views, in view 1 it shows me a list of users, when clicking on any of them you must open another view showing the information about that user in view 2 .
To do that in view 1 with js I capture the user's id and send it to the controller by ajax, and in the controller it sends it to the model and the model response returns to the controller and sends it to view2, to show only the information of the selected user, the question is that it does not work, could you help me, what am I doing wrong?
View 1: This is the paragraph where you click and capture the id and the ajax that sends that id to the controller.
View1
<p onclick="detalles('<?=$p->usuarioId?>');"> <?=$p->usuarioId?><i class="fa fa-check-circle"></i> <?php echo $p->user ?></p>
<script>
function detalles(id=null){
$ (document) .ready (function () {
console.log(id);
$.ajax({
type: "POST",
data : {'id': id},
dataType:"html",
url: "usuarios_admin/ver",
success: function(result)
{
alert("good");
console.log("result",result);
}
});
});
}
</script>
Controller
public function ver(){
$id = $this->input->post("id");
if($id != null) {
$data = $this->PostUser->find($id);
echo json_encode($data);
$this->load->view('usuarios/vista2', $data);
}
}
model:
function find($id){
$this->db->select();
$this->db->from($this->table);
$this->db->where($this->table_id, $id);
$query = $this->db->get();
return $query->row();
}
view2:
here you must see the user data
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 lininfo">
<div class="col-lg-5 col-md-5 col-sm-5 col-xs-5 sinpa">
<p class="colorp">Name:</p>
</div>
<div class="col-lg-7 col-md-7 col-sm-7 col-xs-7 sinpa">
<p class="colorpi"><?php $data['name'] ?></p>
</div>
</div>
try this, i think there should be typo mistake
<p onclick="detalles('<?php echo $p->usuarioId ?>');"> <?php echo $p->usuarioId; ?>
<i class="fa fa-check-circle"></i> <?php echo $p->user ?></p>
Is your 2nd view load after ajax call?
Have you print your return data in ajax success,because you define dataType:"html" in ajax but you return json data from controller.
Thank you for your answers, it came out.
I had to print on the view this way to see the data:
<div class="col-lg-12 col-md-12 col-sm-12 col-xs-12 lininfo">
<div class="col-lg-5 col-md-5 col-sm-5 col-xs-5 sinpa">
<p class="colorp">Name :</p>
</div>
<div class="col-lg-7 col-md-7 col-sm-7 col-xs-7 sinpa">
<p class="colorpi"><?php echo $user->name ?></p>
</div>
</div>
controller:
public function ver(){
$id = $this->input->post("id");
if($id != null) {
$data['user'] = $this->PostUser->find($id);
$this->load->view('usuarios/vista2', $data);
}
}
ajax y view 1
<div class="hi">
<!-- here you would see the result of ajax -->
<div>
<script>
function detalles(id=null){
$ (document) .ready (function () {
console.log(id);
$.ajax({
type: "POST",
data : {'id': id},
dataType:"html",
url: "usuarios_admin/ver",
success: function(result)
{
$('.hi').html(result);
}
});
});
}
</script>

How to use variable data after Ajax Call Success - Laravel

I created a small file manager to manage my files. On the one hand, the folder structure is shown thanks to JsTree. On the right I would like that based on the click on the left folder I was shown the files contained in that folder.
At the click an Ajax call is made which calls the selectFiles method to go through the routes. Now in the console i see the correct data, but i don't know how to use it into foreach in the blade.
AJAX:
// chiamata Ajax per selezionare files in base all'id
$('#treeview').on("select_node.jstree", function (e, data) {
var id = data.node.id;
$.ajax({
type: 'POST',
url: 'archivio_documenti/+id+/selectFiles',
data: {id:id},
success: function(data) {
console.log('Succes!',data);
},
error : function(err) {
console.log('Error!', err);
},
});
});
DocumentiController.php:
/**
* Selzionare files in base all'id della cartella
*/
public function selectFiles(Request $request){
try{
$id = $request->id;
$files = \App\Documento::where('cartella_id',$id)->get();
return response()->json(compact('files'));
}
catch(\Exception $e){
echo json_encode($e->getMessage());
}
}
Route:
Route::post('archivio_documenti/{id}/selectFiles', 'DocumentiController#selectFiles');
Update:
#foreach($files as $key => $file)
<div id="myDIV" class="file-box">
<div class="file">
{!! Form::open(['method' => 'DELETE','route' => ['documento.destroy', $file->id]]) !!}
<button type="submit" class="#" style="background: none; border: none; color: red;">
<i class='fa fa-trash' aria-hidden='true'></i>
</button>
{!! Form::close() !!}
<i class='fa fa-edit' aria-hidden='true'></i>
<input id="myInput_{{$key}}" type="text" value="{{'project.dev/'.$file->path.'/'.$file->file}}">
<i class="btnFiles fa fa-files-o" aria-hidden="true" data-id="{{$key}}"></i>
<a href="{{' http://project.dev/'.$file->path.'/'.$file->file}}">
<span class="corner"></span>
<div class="icon">
<i class="img-responsive fa fa-{{$file->tipo_file}}" style="color:{{$file->color_file}}"></i>
</div>
<div class="file-name">
{{$file->file}}
<br>
<small>Update: {{$file->updated_at}}</small>
</div>
</a>
</div>
</div>
#endforeach
OK, the foreach of yours is a bit complex, but the idea itself is simple: recreate the foreach loop from your Blade in Javascript and append the result to the DOM.
In your success callback you could e.g. do this:
$('#treeview').on("select_node.jstree", function (e, data) {
var id = data.node.id;
$.ajax({
type: 'POST',
url: 'archivio_documenti/+id+/selectFiles',
data: {id:id},
success: function(data) {
// Build the HTML based on the files data
var html = '';
$.each(data, function(i, file) {
html += '<div class="file" id="file_' + file.id + '">' + file.updated_at + '</div>';
});
// Append the built HTML to a DOM element of your choice
$('#myFilesContainer').empty().append(html);
},
error : function(err) {
console.log('Error!', err);
},
});
});
Obviously, this is simplified and you'd need to use the HTML structure you've shown us in the foreach loop above, but the idea is the same: (1) loop through your files in the data object and build the HTML structure row by row, (2) put the whole HTML block in the DOM, wherever you need it to be displayed after the user clicked on a folder.
Alternative:
If you'd like to keep the foreach loop in Blade instead of of Javascipt, you could move the loop to a separate blade:
folder_contents.blade.php
#foreach($files as $key => $file)
<div id="myDIV" class="file-box">
<div class="file">
{!! Form::open(['method' => 'DELETE','route' => ['documento.destroy', $file->id]]) !!}
<button type="submit" class="#" style="background: none; border: none; color: red;">
<i class='fa fa-trash' aria-hidden='true'></i>
</button>
{!! Form::close() !!}
<i class='fa fa-edit' aria-hidden='true'></i>
<input id="myInput_{{$key}}" type="text" value="{{'project.dev/'.$file->path.'/'.$file->file}}">
<i class="btnFiles fa fa-files-o" aria-hidden="true" data-id="{{$key}}"></i>
<a href="{{' http://project.dev/'.$file->path.'/'.$file->file}}">
<span class="corner"></span>
<div class="icon">
<i class="img-responsive fa fa-{{$file->tipo_file}}" style="color:{{$file->color_file}}"></i>
</div>
<div class="file-name">
{{$file->file}}
<br>
<small>Update: {{$file->updated_at}}</small>
</div>
</a>
</div>
</div>
#endforeach
Then, in your controller:
public function selectFiles(Request $request){
try{
$id = $request->id;
$files = \App\Documento::where('cartella_id',$id)->get();
// Save the view as string
$view = view('folder_contents.blade.php', compact('files')))->render();
// Pass the ready HTML back to Javasctipt
return response()->json(compact('view'));
}
catch(\Exception $e){
echo json_encode($e->getMessage());
}
}
you must set header for ajax
headers: {
'X_CSRF_TOKEN':'xxxxxxxxxxxxxxxxxxxx',
'Content-Type':'application/json'
},
and in Controller
public function selectFiles(Request $request){
try{
$id = $request->id;
$files = \App\Documento::where('cartella_id',$id)->get();
return response()->json($files);
}
catch(\Exception $e){
echo json_encode($e->getMessage());
}
}

search with ajax laravel

I need my project to have a search form, I tried with this code, but when I execute console it says:
POST http://localhost:8000/buscar 500 (Internal Server Error)
then here is my view
<div id="qnimate" class="off">
<div id="search" class="open">
<button data-widget="remove" id="removeClass" class="closeSearch" type="button">×</button>
<input type="text" placeholder="Buscar Noticias - Articulos - Reviews" id="buscar" onkeydown="keydownFunction()" onkeyup="keyupFunction()">
<button class="btn btn-lg btn-site" type="submit"><span class="glyphicon glyphicon-search"></span> Buscar</button>
<div id="resultadoBusqueda" class="col-md-12"></div>
</div>
</div>
here is my controller
public function buscar()
{
$keywords = Input::get('keywords');
$reviews = Reviews::where('estado','1')->take();
$buscarReviews = new \Illuminate\Database\Eloquent\Collection();
foreach ($reviews as $review) {
if(Str::contains(Str::lover($review->nombre), Str::lover($keywords)))
$buscarReviews->add($review);
}
return view::make('busqueda')->with('buscarReviews', $buscarReviews);
}
here is the view which shows the information
#foreach($buscarReviews as $review)
<div id="reviews" class="col-md-12">
<div class="col-md-4">
<img src="Imagenes/{{$review->logo}}" width="50">
</div>
<div class="col-md-8">
<h2>{{$review->nombre}}</h2>
<div>{!! str_limit($review->descripcion, $limit = 150, $end = '...') !!}</div>
</div>
</div>
#endforeach
here is my js
var timer;
function keydownFunction(){
timer = setTimeout(function(){
var keywords = $('#buscar').val();
if(keywords.length > 0){
$.post('/buscar', {keywords: keywords}, function(markup){
$('#resultadoBusqueda').html(markup);
});
}
}, 500);
}
function keyupFunction(){
clearTimeout(timer);
}
I don't know what is the reason that it doesn't print the information required.
you are sending post request from ajax but in your controller you are trying to get that value using get, try this code
public function buscar(Request $request)
{
$keywords = $request->keywords;
$reviews = Reviews::where('estado','1')->take();
$buscarReviews = new \Illuminate\Database\Eloquent\Collection();
foreach ($reviews as $review) {
if(Str::contains(Str::lover($review->nombre), Str::lover($keywords)))
$buscarReviews->add($review);
}
return view::make('busqueda')->with('buscarReviews', $buscarReviews);
}
also remember to change in route like this.
Route::post('buscar', 'yourController#buscar');

(Vue.js and Laravel) Array won't refresh after deleting item

I'm new to Vue.js, trying to create a single page blog just to get my feet wet with the vue/laravel combo, and I am stuck when it comes to deleting a "story" from the array of "stories" I am working with. I know the routes are fine because the story actually deletes, no errors are thrown, but the deleted story will remain in the array until I refresh the page. From what I've read elsewhere, the code I have implemented should update the array immediately. I have attached the relevant parts of my blade view, vue.js file, and controller. Thanks in advance!
JS (VUE)
new Vue({
el: '[vue-news]',
search: "",
data: {
stories: ''
},
ready: function() {
// GET request
this.$http.get('/app/news/get', function(data, status, request) {
// set data on vm
this.$set('stories', data);
// console.log(data);
}).error(function(data, status, request) {
// handle error
});
},
methods: {
// DELETE STORY FROM ARRAY
deleteNews: function(id, index) {
this.$http.delete('app/news/' + id + '/delete').success(function(response) {
this.stories.$remove(index);
swal("Deleted!", "Your news story has been deleted.", "success");
}).error(function(error) {
console.log(error);
swal(error);
});
}
}
});
BLADE
<section vue-news>
<div class="row news-row">
<div class="columns large-9 medium-9 small-12">
<article data-id="#{{ story.id }}" class="story panel" v-for="story in stories | filterBy search" track-by="$index">
<h1>#{{ story.title }}</h1>
<p>#{{ story.content }}</p>
<p>#{{ story.created_at }}</p>
<p>#{{ story.id }}</p>
<p>#{{ story.timestamp }}</p>
Read More...
<div class="options">
<a #click="editNews" href="#">
<i class=" edit fa fa-pencil-square-o"></i>
</a>
{{-- DELETE NEWS BUTTON --}}
<a #click.prevent="deleteNews(story.id, $index)" href="#">
<i class="delete fa fa-trash-o"></i>
</a>
</div>
</article>
</div>
<div class="columns large-3 medium-3 small-12">
<input type="text" v-model="search">
</div>
</div>
</section>
CONTROLLER
public function delete($id)
{
return response()->json(News::destroy($id));
}
The $remove method now treats the argument as an item to search for rather than an index. In other words, try this out:
Delete method:
deleteNews: function(id, story) {
this.$http.delete('app/news/' + id + '/delete').success(function(response) {
this.stories.$remove(story);
swal("Deleted!", "Your news story has been deleted.", "success");
}).error(function(error) {
console.log(error);
swal(error);
});
}
HTML section:
<a #click.prevent="deleteNews(story.id, story)" href="#">
<i class="delete fa fa-trash-o"></i>
</a>
Source: https://github.com/vuejs/vue/releases
Edit: Since you are passing the entire story item, you can actually just pass one argument and shorten the code to this:
Vue:
deleteNews: function(story) {
this.$http.delete('app/news/' + story.id + '/delete').success(function(response) {
this.stories.$remove(story);
swal("Deleted!", "Your news story has been deleted.", "success");
}).error(function(error) {
console.log(error);
swal(error);
});
}
HTML:
<a #click.prevent="deleteNews(story)" href="#">
<i class="delete fa fa-trash-o"></i>
</a>

Resources