madsynn's avatar

Uploader Help / Dropzone.js

OVERVIEW

Note: **If anybody could help me I would be greatful. **

  • Im using dropzone.js for image upload and I have heard people saying they have added an id on the create function by creating an "empty" model instance with (id, instance_id*, created_on, updated_on) and then redirect to the edit page one they have the id to attach to the images or files.

**If anyone could show me an example it would be great. **

Is this done in the Route::create ?

Or is this done in the create / store functions in the controller?

I am at a loss on how to attach the id of the model instance when saving to the database. Been working on this for a few days now so would really appreciate the assistance.

If anyone has an example of how this could be done differently I am up to learn that as well. I have gone through the flyers tutorial many times now and still cannot get it to work. Maybe store them temporarily in the sessions then when created move and save them to the database. If this can be done please share an example.

Project Overview:

MODELS:

Product Model:

use Illuminate\Database\Eloquent\Model;

class Product extends Model
{
    protected $guarded  = ['id'];
    public $timestamps = true;
    protected $fillable = ['id','product_name', 'price', 'sku', 'upc', 'description'];
    protected $visible = ['product_name', 'price', 'sku', 'upc', 'description'];
    public function images() {return $this->hasMany(\App\Models\ProductImage::class); }
    public function getPriceAttribute($price)
    {
        return '$'. number_format($price, 2, '.', '');
    }
    public function scopePreUploadImagesBeforeProductCreation($query, $id )
    {
        return $query->where(compact('id'))->first();
    }
}

Photos Model:

namespace App\Models;
use Image;
use Illuminate\Database\Eloquent\Model;
use Symfony\Component\HttpFoundation\File\UploadedFile;

class Photo extends Model{
    public $table = 'photos';
    protected $fillable = [ 'name', 'path'];
    public function product() { return $this->belongsTo(\App\Models\Product::class);  
}

Product Controller

use App\Http\Requests;
use App\Http\Requests\ProductCreateRequest;
use App\Models\Photo;
use App\Product;
use Illuminate\Http\Request;
use Illuminate\Support\Facades\File;
use Illuminate\Support\Facades\Input;
use Illuminate\Support\Facades\Redirect;
use Illuminate\Support\Facades\Response;

class ProductController extends Controller
{
    public function create()
    {
        return view('product.create');
    }

    public function store(Request $request)
    {
       Product::create($request->all());
       flash()->success('Success!', 'Your product has been created');
       return Redirect::route('product.index');
    }
    
    public function show($id)
    {
        $product = Product::findOrFail($id);

        return view('product.show', compact('product'));
    }

    public function addPhoto(Product $product, Request $request)
    {
        $this->validate($request, [
            'photo' => 'required|mimes:jpg,jpeg,png,bmp'
        ]);
        $file = $request->file('photo');
        $name = $file->getClientOriginalName();
        $file->move('uploads/products/{name}');
        $product = Product::where($product)->firstOrFail();
        $product->photos()->create(['path' => "/uploads/products/{name}"]);
        return "done";
    }

}

0 likes
10 replies
madsynn's avatar

This is what I followed but for some reason im still having this issue. not sure how to get past this part.

madsynn's avatar

@Snapy Thank you for your help . I think I might almost have it. will you take a look and see id I have this configured right.

<script type="text/javascript">
        Dropzone.options.addPhotosForm = {
            paramName: 'image',
            autoProcessQueue: false,
            maxFileSize: 3,
            acceptedFiles: '.jpg, .jpeg, .png, .bmp',
             init: function() {
                **var submitButton = document.querySelector("#addPhotosForm")**
                myDropzone = this;
                submitButton.addEventListener("click", function() {
                    myDropzone.processQueue(); 
                });
                myDropzone.on("complete", function(file) {
                    myDropzone.removeFile(file);
                });
            },

        }
    </script>

Do I use the form id to target the process when the other form on the page is submitted? There is not submit button on the dropzone form only the form above it. Targeting Dropzone Form

var submitButton = document.querySelector("#addPhotosForm")


{!! Form::open(['route' =>  'store_photo_path', 'method' => 'POST', 'class' => 'dropzone', 'files'=>true, 'id'=>'addPhotosForm']) !!}
{!! Form::close() !!}

Or target the submit button of the create model form as follows?

var submitButton = document.querySelector("#create-product")

    <div class="form-group">
        <button type="submit" class="btn btn-primary btn-lg" id="create-product">
            Create
        </button>
    </div>

Using

<script type="text/javascript">
        Dropzone.options.addPhotosForm = {
            paramName: 'image',
            autoProcessQueue: false,
            maxFileSize: 3,
            acceptedFiles: '.jpg, .jpeg, .png, .bmp',
             init: function() {
                var submitButton = document.querySelector("#create-product")
                myDropzone = this;
                submitButton.addEventListener("click", function() {
                    myDropzone.processQueue();
                });
                myDropzone.on("complete", function(file) {
                    myDropzone.removeFile(file);
                });
            },

        }
    </script>
Snapey's avatar

Sorry, I've not done it, but I think the approach is to defer processing of dropzone until you have saved the form.

This means saving the form with ajax and then triggering the dropzone upload, by which time the product will exist.

You have seen mentions of the laracasts project flyer, but if memory serves, Jeff creates the flyer before adding any images so the dropzone save can go to a url which includes the id.

Personally, I would do it this way, disable the dropzone area until the product has been saved once. Save it then redirect to the edit form with the dropzone enabled so that pictures can be added. You will probably have to support adding images in an edit context anyway.

Snapey's avatar

To answer this part of your question;

I am at a loss on how to attach the id of the model instance when saving to the database.

if you are editing product 51 then your URL will be something like /product/51/edit

In this case, the URL that dropzone posts to would be /product/51/addPhoto so the id of the model instance is passed in the URL.

madsynn's avatar

@Snapey so something along the lines of

Product::create($request->all());
    flash()->success('Success!', 'Your product has been created');
    return Redirect::route('product.edit', [$product->id]);
Snapey's avatar
Snapey
Best Answer
Level 122

Well, you will need to grab the id of the created product

$product = Product::create($request->all());
    flash()->success('Success!', 'Your product has been created');
    return Redirect::route('product.edit', [$product->id]);
1 like

Please or to participate in this conversation.