Home > OS >  Passing JS variable(array) to Laravel Controller
Passing JS variable(array) to Laravel Controller

Time:11-20

I have a project using JS and Laravel.

In blade.php I have a list of items with checkboxes, the list I retrieve from the external database based on its status. I need to be able to select some items and by one click change its status (for example "archive").

  function getSelected(){
  let selected = new Array()
  let tblTickets = document.getElementById('tblTickets')
  let checked = tblTickets.getElementsByTagName("input")
  for (let i = 0; i < checked.length; i  ) {
    if (checked[i].checked) {
        selected.push(checked[i].value)
    }
 }
  if (selected.length > 0) {
   let nr = selected.map(Number)
    console.log(nr)

 }
}

Here is my JS code which gives me the array of numbers (id(s)- primary keys of selected items)

In web.php I created named route for update:

Route::put("/tickets/update", [TicketsController::class, 'update'])->name('tickets.update');

In ticketsController I have following function:

public function update($ids){
    foreach ($ids as $id) {
        $tickets = DB::connection('secondDB')->table('ticket')
            ->join('ticket_status', 'id', '=', 'status_id')
            ->where('id', '=', $id)
            ->update(['name' => 'Closed']);
    }
     $route= route('tickets.update');
    return view('tickets', [
        'tickets' => $tickets, 
        'route' => $route

}

(its second connected external database, so I cannot make Model for it, so I white query manually)

In tickets.blade I added script so I can access route variable in JS

 <script>
  const ticketsApi = @json($route);
 </script>

My question is - how to POST an array of ids of checked tickets to the "update" function in Controller using the route I pass in blade.php? (I know I can loop as well in JS, but if I'll have 1000 tickets, I gonna need to POST 1000 requests, I find it more effective to loop in PHP).

this one doesn't work

 fetch(route,
    {
        method: "POST",
        body: JSON.stringify(numbers)
    })
    .then(res => res.json())
    .catch(error => {
        console.error('Error:', error);

    })
    .then(data => {
        console.log(JSON.stringify(data));
    });

Thank you for any hints.

Updated:

js function:

function getSelected(){
let payload = new Array()
let tblTickets = document.getElementById('tblTickets')
let checked = tblTickets.getElementsByTagName("input")
for (let i = 0; i < checked.length; i  ) {
    if (checked[i].checked) {
        payload.push(checked[i].value)
    }
}
let numbers = []
if (payload.length > 0) {
    numbers = payload.map(Number)
    console.log(numbers)
}

const putMethod = {
    method : 'PUT',
    headers: {
        'Content-type': 'application/json; charset=UTF-8'
    },
    body: JSON.stringify(numbers)
}
fetch(urlUpdate, putMethod)
    .then(res => res.json())
    .then(data => {
        console.log(data);
    })
    .catch(error => {
        console.error('Error:', error);

    })

}

web.php:

Route::put("/tickets/update", [TicketsController::class, 'update'])->name('tickets.update');

Controller:

 public function update(Request $request): \Illuminate\Http\JsonResponse
{
    $request->validate([
        'ids' => ['required', 'array', 'min:1'],
        'ids.*' => ['integer']
    ]);
        $tickets = DB::connection('secondDb')->table('ticket')
            ->join('ticket_status', 'id', '=', 'status_id')
            ->whereIn('id', $request->input('ids'))
            ->update(['name' => 'Closed ']);


    return response()->json([
        'ticketsUpdated' => $tickets
    ]);

}

I still recieve two errors: action.js:57 PUT http://mypath/tickets/update 419 (unknown status) action.js:63 Error: SyntaxError: Unexpected token < in JSON at position 0

I really cannot figure out how to pass my array, split it on numbers as id and update database. I have an build in update route for internal database. But for external I cannot use safe() and build in function provides with an id in route /bills/{id}, but I want to update a bunch of them, not one by one

CodePudding user response:

First you use the POST method in your fetch request, while your route uses the PUT verb. So you have to change the method specified in your fetch to PUT.

Here are some problems with your controller:

  1. Your id array is in your request body and not as a parameter of the URL, so you need to adapt your controller action to use the Request.

  2. You want to use a route with a list of id's to avoid making 1000 queries to the database, but you are doing exactly this because you are using a foreach and it is not optimized. You can use whereIn() instead.

  3. Knowing that you are using fetch, prefer to return a JSON response rather than a view.

Here is a code example:

public function update(Request $request)
{
    $request->validate([
        'ids' => ['required', 'array', 'min:1'],
        'ids.*' => ['integer']
    ]);

    $tickets = DB::connection('secondDB')->table('ticket')
            ->join('ticket_status', 'id', '=', 'status_id')
            ->whereIn('id', $request->input('ids'))
            ->update(['name' => 'Closed']);

    return response()->json([
      'ticketsUpdated' => $tickets;
    ]);
}

CodePudding user response:

Thx everyone. I found the solution to make it work without JS only Laravel

in blade:

 <form action="/tickets/update" method="POST">
 @csrf
 @method('PUT')

 @foreach($tickets as $ticket)

                <tr>
                    <td>
                        <input class="check" type="checkbox" id="{{$ticket->ticket_id}}" value="{{$ticket->ticket_id}}" name="ids[]" >
                    </td>

in controller:

 public function update(Request $request)
{
    $numbers = $request->input('ids');
    foreach ($numbers as $number)
    {
        $tickets = DB::connection('osdtbs')->table('ticket')
            ->where('ticket_id', '=', $number)
            ->update(['status_id' => '7']);
    }


    return redirect('/tickets');

}
  • Related