nested set save to database - ajax

I'm trying to implement jqTree with Laravel app.
Controller gets data and return view:
public function index()
{
$categories = Category::get(['id', 'name', '_lft', '_rgt', 'parent_id'])->toTree();
return view('category.index', [
'categories' => $categories
]);
}
Here is a view (javascript part):
var data = {!! $categories !!};
$('#tree').tree({
data: data,
dragAndDrop: true,
onDragStop: handleMove,
});
function handleMove() {
var treeData = $('#tree').tree('toJson');
$.ajax({
url: 'category',
type: 'POST',
headers: { 'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content') },
data: { data: treeData },
});
}
This builds tree properly and I can drag & drop items. However, I want to save reordered tree back to database. Here is a post method in a controller:
public function store(Request $request)
{
$data = $request->data;
$result = Category::rebuildTree($data);
...
}
After calling rebuildTree method, I'm getting this error:
Type error: Argument 1 passed to Kalnoy\\Nestedset\\QueryBuilder::rebuildTree() must be of the type array, string given
I have tried with this:
public function store(Request $request)
{
$data = $request->data;
$data = json_decode($request->data);
$array_data = (array) $data;
$result = Category::rebuildTree($data);
...
}
This however returns:
Cannot use object of type stdClass as array
How can I get array of data passed so I can use rebuildTree() method and update database?
Here is a result of dd($request->data):
[{"name":"Storage","id":3,"_lft":17,"_rgt":18,"parent_id":null,"is_open":true,
"children":[{"name":"Laptops","id":1,"_lft":1,"_rgt":10,"parent_id":null,"is_open":true,
"children":[{"name":"Monitors","id":2,"_lft":11,"_rgt":16,"parent_id":null,
"children":[{"name":"IPS","id":5,"_lft":14,"_rgt":15,"parent_id":2}]},
{"name":"Macbook","id":6,"_lft":2,"_rgt":3,"parent_id":1},
{"name":"Acer","id":7,"_lft":4,"_rgt":5,"parent_id":1},
{"name":"New Subcategory Name","id":8,"_lft":6,"_rgt":7,"parent_id":1},
{"name":"New Subcategory ame","id":9,"_lft":8,"_rgt":9,"parent_id":1}]}]},
{"name":"Memory","id":4,"_lft":19,"_rgt":20,"parent_id":null}]
Also, just to be clear: I'm using jqTree
Nested set is lazychaser/laravel-nestedset

You are getting json in $request->data; you need to decode it in array using json_decode() along with second parameter as true for assoc
see the manual
assoc
When TRUE, returned objects will be converted into associative
arrays.
public function store(Request $request)
{
$result = Category::rebuildTree(json_decode($request->data,True));
...
}
and if you need to pass it in $data then pass it like this.
$data = json_decode($request->data,True);
Alternatively
foreach ($request->data as $value)
$array[] = $value->name;
then pass this $array into your query like this
$result = Category::rebuildTree($array);

Related

Render Laravel Component via Ajax method

How can i render component that is sent from controller via an ajax request? For example i want to dynamically filter product using this method:
Load the index URL
Fetch the products based on the filter category or return all the products using ajax
My ajax Code:
$(document).ready(function () {
filterData();
// Filter data function
function filterData() {
// Initializing loader
$('#product-listing-row').html('<div id="loading" style="" ></div>');
var action = 'fetchData';
var subCategory = getFilter('sub-category');
/* LARAVEL META CSRF REQUIREMENT */
$.ajaxSetup({
headers: {
'X-CSRF-TOKEN': $('meta[name="csrf-token"]').attr('content')
}
});
// Ajax Call
$.ajax({
url: "/shop/filter",
method: "POST",
data: {action: action, subCategory: subCategory},
success: function (data) {
$('#product-listing-row').html(data);
}
});
}
// Get Filter by class name function
function getFilter(className) {
var filter = [];
$('.' + className + ':checked').each(function () {
filter.push($(this).val());
});
//console.log(filter);
return filter;
}
$('.common-selector').click(function () {
filterData();
});
});
I am getting all the filters from ProductController
Instead of manually writing html in controller I want to return the specific component from the controller
ProductController:
public function productFilter() {
if (!request()->action) abort('500');
// Starting the query for products which are active
$products = Product::where('is_active', '1');
//dump(request()->subCategory);
/* Checking the filters */
// sub category exists
if (request()->subCategory) $products = $products->where('sub_category_id', request()->subCategory);
// Completing the query
$products = $products->orderBy('created_at', 'DESC')->paginate(15);
// Adding reviews and total review
$products = Product::setProductReviewTotalReviewsAttr($products);
foreach ($products as $product)
//view('components.shop-product', ['product' => $product])->render();
echo '<x-shop-product :product="$product"></x-shop-product>';
}
Instead of getting the components rendered, I am receiving the whole string echoed out. Is there any way i can just get the components rendered?
Thanks in advance
Actually now I found a way to do it myself
I applied the following to the ProductController
return View::make("components.shop-product")
->with("product", $product)
->render();
Updated Code:
public function productFilter() {
if (!request()->action) abort('500');
// Starting the query for products which are active
$products = Product::where('is_active', '1');
//dump(request()->subCategory);
/* Checking the filters */
// sub category exists
if (request()->subCategory) $products = $products->where('sub_category_id', request()->subCategory);
// Completing the query
$products = $products->orderBy('created_at', 'DESC')->paginate(15);
// Adding reviews and total review
$products = Product::setProductReviewTotalReviewsAttr($products);
$output = '';
foreach ($products as $product) {
$output .= View::make("components.shop-product")
->with("product", $product)
->render();
}
if (count($products) > 0)
echo $output;
else
echo '<div class="col">No Data</div>';
}
with laravel > 8 you can use \Blade::render directly in your controller to render even anonymouse components, here I'm rendering a table component with a lot of properties:
class componentController extends Controller {
public function index(){
$table = [
:tableid => "table"
:thead => ["id","name","job"]
:data => [
["1","marcoh","captain"],
["2","sanji","cook"]
],
tfoot => false
];
// Renders component table.blade.php
return \Blade::render('
<x-table
:tableid="$tableid"
:thead="$thead"
:data="$data"
tfoot
/>
', $table);
...

Laravel How I can return view data with respone json (both in 1 time)?

public function index(Request $request)
{
$search_book = $request->id;
$proc=DB::select(DB::raw("SELECT * FROM BOOKS WHERE BOOKID = '$Search_book'")
if ($search_book!="") {
return response()->json($proc);
return view('status.status',[
'proc' => $proc
]);
}
How to return 2 data
To determine if a request is an ajax request, you can use the ajax() method on a Request object injected into the controll action:
public function index(Request $request)
{
$results = DB::table('books')
->where('bookid', $request->id)
->get();
if ($request->ajax()) {
return response()->json($results);
}
return view('status.status', [
'proc' => $results
]);
}
I went ahead and fixed the SQL injection vulnerability in your query for you by swapping the query for a proper one. It could still be improved by using a Book model instead of a plain database query, but it is fine this way as well.
The query from your comment can be simplified by replacing the left join. Simply take the sub query as base and right join it with processspj:
DB::table('processtrans as pt')
->leftJoin('processmaster as pm', 'pm.pcm_id', '=', 'pt.pct_pcm_id')
->rightJoin('processspj as ps', 'ps.pc_id', '=', 'pt.pct_pc_id')
->where('pt.pct_pc_id', $request->id)
->select([
'ps.*',
'pm.pcm_bname',
'pt.created_at',
'pt.updated_at',
'pt.pct_id',
'pt.pct_leadtime',
'pt.pct_pcm_id',
'pt.pct_pc_id',
'pt.pct_planfinishdate',
'pt.pct_startdate',
'pt.pct_status',
])
->get();
$(document).ready(function(){
$("#dl_books").change(function()
{
var getValue=$(this).val();
$.ajax({
type: 'GET',
url: '{{route('status')}}',
data: {id:getValue},
success:function(data)
{
//Json for value textbox
$("#txtbookname").text(data[0].pcm_bname);
}
});
});
});
Just save the rendered view in a variable and do a json response:
public function index(Request $request) {
$results = DB::table('books')
->where('bookid', $request->id)
->get();
if ($results) {
$view = view('status.status', [
'proc' => $results
])->render();
return response()->json(['view'=> $view, 'proc' => '$results']);
}
}

How to pass id from ajax to controller - Laravel & Ajax

Currently, i am on the show page that is i am running the function show as in my controller so my url is showing like dashboard/1/people in the url address bar. Now, when i click on a person, it routes to a different page and that is where getPeople is called.
How can i get the id of the person i clicked which is 1 from the ajax request in the scripts and pass to my controller?
PS: At the moment, i have hardcoded 1 in the ajax request but i want it to be dynamic please
How do i get this done?
Script
datatable = $('#table').DataTable({
"ajax": "{{ route('dashboard/1/people') }}",
"columns": [
{data: 'check', name: 'check'},
],
Controller
public function show($id)
{
$class = Class::whereId($id)->first();
return view('show');
}
public function getPeople($id)
{
$get_id = $id;
$class = Class::whereId($get_id)->first();
$people = $class->peoples()->get();
return Datatables::of($people)->addColumn('action', function ($ppl) {
//return
})->make(true);
}
This should work:
In your getPeople method store the id in a session variable:
public function getPeople($id)
{
$get_id = $id;
//using session helper method
session(['show_id' => $id]);
$class = Class::whereId($get_id)->first();
$people = $class->peoples()->get();
return Datatables::of($people)->addColumn('action', function ($ppl) {
//return
})->make(true);
}
and then access it in you ajax code:
datatable = $('#table').DataTable({
"ajax": "{{ route('dashboard/'.session('show_id').'/people') }}",
"columns": [
{data: 'check', name: 'check'},
],
DataTable ajax allows yo to pass extra parameters in object format just like this:
datatable = $('#table').DataTable({
"ajax": {
"type": "GET",
data:{id: my_id_var},
"url": "my_route"
}
}
And in your function just get the Request var
public function getPeople(Request $request){
$get_id = $request->id;
$class = Class::whereId($get_id)->first();
$people = $class->peoples()->get();
return Datatables::of($people)->addColumn('action', function ($ppl) {
//return
})->make(true);
}
More Information in Sorce Page

How get data from ajax object in controller Laravel?

In ajax I have 3 objects 'emp_info, leave_detail, and leave_items' in controller I don't know how to get record of each object. Could you help me please?
$.ajax({
type: 'POST',
url: '/leave-request-initiator/store',
data: {_token: $('#_token').val(), emp_info: $('#frm_emp_info').serialize(), leave_detail: $('#frm_leave_detail').serialize(), leave_items: leave_items},
beforeSend: function () {
console.log('sending');
},
success: function (response) {
console.log(response);
}
});
Controller.
public function store(Request $request)
{
$data = $request->all();
foreach ($data->emp_info as $item){
$empcode = $item['EMPCODE'];
}
$leaveDetail = new HREmpLeave([
'EMPCODE' => $empcode,
'LEAVECODE' => $request->get('LEAVECODE'),
'FROMDATE' => $request->get('FROMDATE'),
'TODATE' => $request->get('TODATE'),
'BACKTOWORKON' => $request->get('BACKTOWORKON'),
'NODAY' => $request->get('NODAY'),
'REMARK1' => $request->get('REMARK1')
]);
$leaveDetail->save();
}
Change this:
$data = $request->all();
foreach ($data->emp_info as $item){
$empcode = $item['EMPCODE'];
}
to this:
$emp_info = parse_str($request->emp_info); //parse into a array
$empcode = $emp_info['EMPCODE'];

Input array loop on controller laravel 5

I have inputs array and i need to make a foreach but laravel $request->all() only return last one:
url:
http://localhost:8000/api/ofertas?filter_pais=1&filter_pais=2&filter_pais=3
controller:
public function filtroOfertas(Request $request){
return $request->all();
}
result:
{"filter_pais":"3"}
result should return 1, 2 and 3 and i need to make a foreach in filter_pais.
Any solution? Thanks
Use [] at the key of query string.
http://localhost:8000/api/ofertas?filter_pais[]=1&filter_pais[]=2&filter_pais[]=3
It will be parsed as array.
Repeated parameters make no sense and should be avoided without exception.
But looking at other solutions, there are several:
routes.php
Route::get('/api/ofertas/{r}', 'Controller#index');
Controller:
public function index($r)
{
$query = explode('&', $r);
$params = array();
foreach($query as $param)
{
list($name, $value) = explode('=', $param);
$params[urldecode($name)][] = urldecode($value);
}
// $params contains all parameters
}
Given that the URL has no question marks:
http://localhost:8000/api/ofertas/filter_pais=1&filter_pais=2&filter_pais=3

Resources