Nikki's avatar
Level 1

Redirect not working 100%

I've created a page where once you've uploaded images and click on the upload button it uploads the images and saves it to the database. The problem I'm having is that my redirect isn't working.

If I do

return ['redirect' => route('products.index')];

my page doesn't go to the correct page but in my network tab it gives me the correct url. In my Response tab I have

redirect    http://vue-laravel-image.test/admin/products

If I do

return redirect()->route('products.index')->with('success', 'Product Successfully Added.');

I get a blank Response but then I get another line with the correct html for the product.index page but on my browser it hasn't changed to the correct page.

This is my controller

<?php

namespace App\Http\Controllers;

use Illuminate\Http\Request;

use App\Product;

class ProductsController extends Controller
{
    public function index()
    {
        $products = Product::all();

        return view('admin.products.products.index', compact('products'));
    }

    public function create()
    {
        $product = new Product();

        return view('admin.products.products.create');
    }

    public function store(Request $request)
    {
        $product = new Product();

        $input = $this->getSafeInput($request);

        $product->fill($input);

        if($request->hasFile('images'))
        {
            $names = [];
            foreach($request->file('images') as $image)
            {
                $destinationPath = 'product_images/full_image/';
                $filename = $image->getClientOriginalName();
                $image->move($destinationPath, $filename);
                array_push($names, $filename);          
            }

            $product->image = json_encode($names);
        }


        $product->save();

        return redirect()->route('products.index')->with('success', 'Product Successfully Added.');
        // return ['redirect' => route('products.index')];
    }

    protected function getSafeInput(Request $request)
    {
        return $request->only([
            'image',
        ]);
    }
}

and here is my Vue component

<template>
    <!-- isDragging = if(isDragging) -->
    <div class="uploader" 
            @dragenter="OnDragEnter" 
            @dragleave="OnDragLeave" 
            @dragover.prevent 
            @drop="onDrop" 
            :class="{ dragging: isDragging }">
        
        <div class="upload-control" v-show="images.length">
            <label for="file">Select a file</label>
            <button @click="upload">Upload</button>
        </div>

        <!-- only shows if there is no images -->
        <div v-show="!images.length">
            <i class="fa fa-cloud-upload"></i>
            <p>Drag your images here</p>
            <div>OR</div>
            <div class="file-input">
                <label for="file">Select a file</label>
                <input type="file" id="file" @change="onInputChange" multiple>
            </div>
        </div>

        <!-- if there is images -->
        <div class="images-preview" v-show="images.length">
            <div class="img-wrapper" v-for="(image, index) in images">
                <img :src="image" :alt="`Image Uplaoder ${index}`">
                <div class="details">
                    <span class="name" v-text="files[index].name"></span>
                    <span class="size" v-text="getFileSize(files[index].size)"></span>
                </div>
                <div class="btn btn-danger" @click="funDeleteFile(index)">
                    Remove
                </div>
            </div>
        </div>
    </div>
</template>

<script>
export default {
    data: () => ({
        isDragging: false,
        //Sets the dragCount to 0
        dragCount: 0,
        //Makes files an array, so that we can send the files to the server
        files: [],
        //Makes images an array, so that we can let the user see the images
        images: [],
    }),
    methods: {
        OnDragEnter(e) {
            //Prevents the default action of the browser
            e.preventDefault();
            
            // This lets the dragCount become 1, so that the image uploader changes colour
            this.dragCount++;

            // Changes the isDragging variable to true instead of false
            this.isDragging = true;

            return false;
        },
        OnDragLeave(e) {
            //Prevents the default action of the browser
            e.preventDefault();

            // This lets the dragcount become 0, so that the image uploader changes to it's original colour
            this.dragCount--;

            // This is if the dragCount is <= 0 then the isDragging variable is false
            if (this.dragCount <= 0)
                this.isDragging = false;
        },
        onInputChange(e) {
            // Grabs the files from the event
            const files = e.target.files;

            // Creates an array for files, so that we can loop thru it
            // Send the file to the addImage method via "this.addImage(file)"
            Array.from(files).forEach(file => this.addImage(file));
        },
        onDrop(e) {
            //Prevents the default action of the browser
            e.preventDefault();
            //Stops the propagation into the other elements inside the one we drop and file into
            e.stopPropagation();

            // This is to disable the dragging of the images
            this.isDragging = false;

            // Grabs the files from the event
            const files = e.dataTransfer.files;

            // Creates an array for files, so that we can loop thru it
            // Send the file to the addImage method via "this.addImage(file)"
            Array.from(files).forEach(file => this.addImage(file));
        },
        addImage(file) {
            //Checks if the file type is an image
            if (!file.type.match('image.*')) {
                this.$toastr.e(`${file.name} is not an image`);
                return;
            }

            this.files.push(file);

            const img = new Image(),
                reader = new FileReader();

            reader.onload = (e) => this.images.push(e.target.result);

            reader.readAsDataURL(file);
        },

        funDeleteFile(file){
            console.log('delete '+file)
            this.files.splice(file, 1)
            this.images.splice(file, 1)
   
        },

        getFileSize(size) {
            const fSExt = ['Bytes', 'KB', 'MB', 'GB'];
            let i = 0;
            
            while(size > 900) {
                size /= 1024;
                i++;
            }

            return `${(Math.round(size * 100) / 100)} ${fSExt[i]}`;
        },
        upload() {
            const formData = new FormData();
            
            this.files.forEach(file => {
                formData.append('images[]', file, file.name);
            });

            axios.post('/admin/products', formData)
                .then(response => {
                    this.$toastr.s('All images uplaoded successfully');
                    // this.images = [];
                    // this.files = [];
                })
        }
    }
}
</script>

If there is anything else you would like me to post please let me know. Thanks

0 likes
14 replies
munazzil's avatar

Can you type below code in your command propmt and display result over here.

 php artisan route:list
Nikki's avatar
Level 1

@munazzil - sure


+--------+-----------+-------------------------------+------------------+-------------------------------------------------+--------------+
| Domain | Method    | URI                           | Name             | Action                                          | Middleware   |
+--------+-----------+-------------------------------+------------------+-------------------------------------------------+--------------+
|        | GET|HEAD  | /                             |                  | Closure                                         | web          |
|        | GET|HEAD  | admin/products                | products.index   | App\Http\Controllers\ProductsController@index   | web          |
|        | POST      | admin/products                | products.store   | App\Http\Controllers\ProductsController@store   | web          |
|        | GET|HEAD  | admin/products/create         | products.create  | App\Http\Controllers\ProductsController@create  | web          |
|        | GET|HEAD  | admin/products/{product}      | products.show    | App\Http\Controllers\ProductsController@show    | web          |
|        | PUT|PATCH | admin/products/{product}      | products.update  | App\Http\Controllers\ProductsController@update  | web          |
|        | DELETE    | admin/products/{product}      | products.destroy | App\Http\Controllers\ProductsController@destroy | web          |
|        | GET|HEAD  | admin/products/{product}/edit | products.edit    | App\Http\Controllers\ProductsController@edit    | web          |
|        | GET|HEAD  | api/user                      |                  | Closure                                         | api,auth:api |
|        | POST      | images-upload                 |                  | App\Http\Controllers\ImagesController@upload    | web          |
+--------+-----------+-------------------------------+------------------+-------------------------------------------------+--------------+
munazzil's avatar

Can you show you resource/view/... folder for that products.index? and your web.php?

Nikki's avatar
Level 1

@munazzil - Here it is

@extends('layouts.admin')
@section('content')
    @if($message = Session::get('success'))
        <div class="alert alert-success success-msg">
            <p>
                {{ $message }}
            </p>
        </div>
    @endif

    {{ Html::linkRoute('products.create', 'Create Product', array(), array('class' => 'btn btn-info mb-15')) }}

    <div class="card border-dark">
        <div class="card-header">
            <div class="card-title">
                Products
            </div>
        </div>
        
        @foreach($products as $product)
            {{ $product->image }}
        @endforeach

    </div>
@endsection

and here is my admin layout just in case

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="utf-8">
  <meta http-equiv="X-UA-Compatible" content="IE=edge">
  <meta name="viewport" content="width=device-width, initial-scale=1, shrink-to-fit=no">
  <meta name="description" content="">
  <meta name="author" content="">
  <meta name="csrf-token" content="{{ csrf_token() }}">
  
  <title>Admin</title>

  <link rel="stylesheet" href="https://use.fontawesome.com/releases/v5.5.0/css/all.css" integrity="sha384-B4dIYHKNBt8Bc12p+WXckhzcICo0wtJAoU8YZTY5qE0Id1GSseTk6S+L3BlXeVIU" crossorigin="anonymous">
  <link href="{{ asset('css/admin/admin.css') }}" rel="stylesheet">
  <link href="{{ asset('css/admin/jquery-ui-demo.css') }}" rel="stylesheet">
  <link rel="stylesheet" href="https://blueimp.github.io/Gallery/css/blueimp-gallery.min.css">
  <link href="{{ asset('css/admin/jquery.fileupload.css') }}" rel="stylesheet">
  <link href="{{ asset('css/admin/jquery.fileupload-ui.css') }}" rel="stylesheet">
  <!-- <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.6/css/bootstrap.min.css"> -->
  <!-- <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css" integrity="sha384-MCw98/SFnGE8fJT3GXwEOngsV7Zt27NXFoaoApmYm81iuXoPkFOJwJ8ERdknLPMO" crossorigin="anonymous"> -->

  <!-- Bootstrap core JavaScript-->
  <script src="{{ asset('js/admin/jquery-3.2.1.min.js') }}"></script>
  <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/dark-hive/jquery-ui.css" id="theme">
  <script src="{{ asset('js/admin/bootstrap.bundle.min.js') }}"></script>
  <script src="{{ asset('js/admin/jquery.easing.js') }}"></script>
  <script src="{{ asset('js/admin/jquery.form.js') }}"></script>

  <script src="{{ asset('js/admin/admin.js') }}"></script>
  <script src="{{ asset('js/app.js') }}" defer></script>

</head>

<body class="fixed-nav sticky-footer bg-dark" id="page-top">
  <!-- BEGIN NAVIGATION-->
    @include('layouts.partials.nav')
  <!-- END NAVIGATION -->

  <div class="content-wrapper">
    <!-- BEGIN CONTENT AREA -->
    <div class="container-fluid">
      <div class="row">
        <div class="col-12">
          @yield('content')
        </div>
      </div>
    </div>
    <!-- END CONTENT AREA -->
    <footer class="sticky-footer">
      <div class="container">
        <div class="text-center">
          <small>Copyright © Your Website 2018</small>
        </div>
      </div>
    </footer>
    <!-- Scroll to Top Button-->
    <a class="scroll-to-top rounded" href="#page-top">
      <i class="fa fa-angle-up"></i>
    </a>
    <!-- Logout Modal-->
    <div class="modal fade" id="exampleModal" tabindex="-1" role="dialog" aria-labelledby="exampleModalLabel" aria-hidden="true">
      <div class="modal-dialog" role="document">
        <div class="modal-content">
          <div class="modal-header">
            <h5 class="modal-title" id="exampleModalLabel">Ready to Leave?</h5>
            <button class="close" type="button" data-dismiss="modal" aria-label="Close">
              <span aria-hidden="true">×</span>
            </button>
          </div>
          <div class="modal-body">Select "Logout" below if you are ready to end your current session.</div>
          <div class="modal-footer">
            <button class="btn btn-secondary" type="button" data-dismiss="modal">Cancel</button>
            <a class="btn btn-primary" href="#">Logout</a>
          </div>
        </div>
      </div>
    </div>

  </div>
</body>

</html>
munazzil's avatar

In your store controller function try like below in redirect instead of route('products.index').

return redirect()->route('admin.products.index')->with('success', 'Product Successfully Added.');
RonB1985's avatar

Your redirect should be working fine:

return redirect()->route('products.index');

Have you got this problem in production as well? Tried a different browser? Cleared cache?

Perhaps try redirecting to a different route, just to troubleshoot if that isn't working correctly either? If so, you know it's not a problem with the route or your controller, etc..

I cannot see anything wrong with your code so..

Nikki's avatar
Level 1

I've tried all that and still nothing.

Could it be maybe I got this in my Response payload

{"redirect":"http:\/\/shop-test.test\/admin\/dashboard"}
AddWebContribution's avatar

You should try this:

return redirect()->route('products.index'');

or

return Redirect::to('/admin/products');
Nikki's avatar
Level 1

@SAURABHD - When I do both of them it doesn't redirect there and my Response tab has the page but not my browser

adamprickett's avatar
Level 6

You're returning a RedirectResponse to an async request so the browser isn't going to perform the redirect.

You'll need to handle your redirect within your JS, either in your axios .then() method, or using an interceptor.

Try returning your Controller response to return ['redirect' => route('products.index')]; and then adding this to your .then() method:

if (response.data.redirect) {
    window.location.href = response.data.redirect
}

Alternatively, you might be able to handle this via the status code and HTTP headers:

if (response.data.status === 302) {
    window.location.href = response.data.headers.location
}
1 like

Please or to participate in this conversation.