0

I'm new to coding and I want to upload a product image upon completing of the new product form in a modal tag in my blade.php.

However, my data are unable to be posted into the database and the file is also not uploading to the server. Please kindly advise on what I should do to solve this issue. Thanks in advance!

This is my View:

<form action="{{route('merchant.product.new')}}" id="form" method="POST" enctype="multipart/form-data">
  @csrf
            <div class="modal-body">
                <div class="form-group">
                    <label for="prodName"> Product Name:</label> <small style="color: red">*</small>
                    <input type="text" id="prodName" class="form-control" name="prodName" value="" maxlength="55" placeholder="Product Name" required>
                </div>
                <div class="form-group">
                    <label for="prodCode"> Product Code:</label> <small style="color: red">*</small>
                    <input type="text" id="prodCode" class="form-control" name="prodCode" value="" maxlength="55" placeholder="Product Code" required>
                </div>
                <div class="form-group">
                    <label for="prodDesc"> Description:</label> <small style="color: red">*</small>
                
                    <textarea id="prodDesc"  name="prodDesc" rows="5" maxlength="255" placeholder="Product Description" class="form-control" required></textarea>
                </div>
                <div class="form-group">
                    <label for="age">Price:</label> <small style="color: red">*</small>
                    <input type="text" id="price" class="form-control" name="price" placeholder="Product Price" required>
                </div>
                <div class="form-group">
                    <label for="age">Quantity:</label>
                    <input type="number" id="quantity" class="form-control" name="Quantity" min="0" value="0">
                </div>
                <div class="form-group">
                    <label for="text">Feature Product</label>
                    <div class="switch">
                        <input type="checkbox" name="featured" id="featured" class="switch-input" value="1"/>
                        <div class="circle"></div>
                    </div>
                </div>
                <div class="form-group">
                    <label for="image">Choose Main Image</label>
                    <input type="file" name="image" id="image">
                </div>
            </div>

            <!-- Modal footer -->
            <div class="modal-footer">
                <button type="submit" class="btn btn-primary" id="new_productsave_btn" data-loading-text="<i class='fa fa-spinner fa-spin'></i> saving..">Save</button>
                <button type="button" class="btn btn-outline-primary" id="close_btn" data-dismiss="modal">Close</button>
    </div>
</form>

Below is my script:

$(document).ready(function(e) {
            var selectedProductId = null;
            var selectedProductCode = null;
            var pageAction = null;
    
            //javascript to filter table
            var productsTable = $('#products_table').DataTable({ 
                stateSave: true,
                columnDefs: [{
                        "searchable": false,
                        "orderable": false,
                        "targets": 0
                },{
                        "searchable": true,
                        "orderable": true,
                        "targets": 1
                },{
                        "searchable": true,
                        "orderable": true,
                        "targets": 2
                },{
                        "searchable": false,
                        "orderable": false,
                        "targets": 3
                },{
                        "searchable": true,
                        "orderable": true,
                        "targets": 4
                },{
                        "searchable": true,
                        "orderable": true,
                        "targets": 5
                },{
                        "searchable": true,
                        "orderable": true,
                        "targets": 6
                },{
                        "searchable": false,
                        "orderable": false,
                        "targets": 7
                }],
                order: [[ 1, 'asc' ]]
            });
    
            productsTable.on( 'order.dt search.dt', function () {
                productsTable.column(0, {search:'applied', order:'applied'}).nodes().each( function (cell, i) {
                    cell.innerHTML = i+1;
                });
            }).draw();
    
            $('#addproduct_btn').click(function() {
                //pageAction = "add";
                $('#myModalNewProduct').modal({backdrop: 'static', keyboard: false});
                $('#myModalNewProduct .modal-title').html('New Product');
            });
    
            $('#new_productsave_btn').click(function() {
                let prodName = $('#prodName').val();
                let prodCode = $('#prodCode').val();
                let prodDesc = $('#prodDesc').val();
                let price = parseFloat($('#price').val().replace(/[^\d.]/g, ''));
                let quantity = $('#quantity').val();
                var featured = [];
                $('#featured').each(function(){
                  if ($(this).is(":checked")) {
                    featured.push($(this).val());
                  }
                });
    
                featured = featured.toString();
                if (prodCode == "") {
                    alert("Product Code can't be empty.");
                    return;
                }
                if (prodDesc == "") {
                    alert("description can't be empty.");
                    return;
                }
                if (price == "") {
                    alert("price can't be empty.");
                    return;
                }
                if (Number.isNaN(price)) {
                    alert("price must be numeric.");
                }
    
                //let url = pageAction == "add" ? @json($domain)+"/products/new" : @json($domain)+"/products/update";
                let data = {prodID: selectedProductId, prodName: prodName, prodCode: prodCode, prodDesc: prodDesc, quantity: quantity, price: price, 
                featured: featured,
                };
                $(this).data('original-text', $(this).html()).html($(this).data('loading-text')).prop('disabled', true);
                $.ajax({
                    type: "POST",
                    url: "{{ route('merchant.product.new') }}",
                    headers: { 
                        'X-CSRF-TOKEN': '{{ csrf_token() }}',  
                        'Content-Type': 'application/json'
                    },
                    data: JSON.stringify(data),
                    dataType: "text",
                    success: function(data) { 
                        if (data == 0) {
                            $('#new_productsave_btn').html( $('#new_productsave_btn').data('original-text')).prop('disabled', false);
                            showNotify("Product Code already exist", "error");
                            return;
                        } else if (data < 0) {
                            $('#new_productsave_btn').html( $('#new_productsave_btn').data('original-text')).prop('disabled', false);
                            showNotify("Something went wrong", "error");
                            return;
                        }
                        showNotify("New product has been added successfully", "success");
                        location.reload();
                    },
                    error: function(data) {
                        $('#new_productsave_btn').html( $('#new_productsave_btn').data('original-text')).prop('disabled', false);                        
                        console.log(data);
                        showNotify("Something went wrong", "error");
                    }
                });
            });
});

Below is my dd($request->all())

array:7 [▼
      "_token" => "pfPg4Grw7MXzDQwBeDAcBN83sZm06LK89GzlNdbY"
      "prodName" => "123213"
      "prodCode" => "123123"
      "prodDesc" => "123213"
      "price" => "123123"
      "Quantity" => "123"
      "image" => Illuminate\Http\UploadedFile {#359 ▼
        -test: false
        -originalName: "roasted-chicken.png"
        -mimeType: "image/png"
        -error: 0
        #hashName: null
        path: "C:\xampp\tmp"
        filename: "php6D72.tmp"
        basename: "php6D72.tmp"
        pathname: "C:\xampp\tmp\php6D72.tmp"
        extension: "tmp"
        realPath: "C:\xampp\tmp\php6D72.tmp"
        aTime: 2021-01-13 10:25:05
        mTime: 2021-01-13 10:25:05
        cTime: 2021-01-13 10:25:05
        inode: 5066549581112407
        size: 699931
        perms: 0100666
        owner: 0
        group: 0
        type: "file"
        writable: true
        readable: true
        executable: false
        file: true
        dir: false
        link: false
        linkTarget: "C:\xampp\tmp\php6D72.tmp"
      }
    ]

This is my controller method:

public function new (Request $request) {
        
        if ($this->isCodeExist($request->{'prodCode'})) {
            return 0;
        }
        else {
            $product = Product::create($request->all());
            if($request->hasFile('image')) {
                // Upload path
                $destinationPath = 'img/products/';
                // Get File
                $image = $request->file('image');
                // Get File Name
                $imageName = time().'_'.$image->getClientOriginalName();
                // Uploading File to given path
                $image->move($destinationPath,$imageName);
                
                // $fileModel->name = time().'_'.$req->file->getClientOriginalName();
                // $fileModel->file_path = '/storage/' . $filePath;
                // $fileModel->save();
            
                try {
                    //$db = new Product();
                    $product->prodName = $request->{'prodName'};
                    $product->prodCode = $request->{'prodCode'};
                    $product->prodImage = $imageName;
                    $product->prodDesc = $request->{'prodDesc'};
                    $product->price = $request->{'price'};
                    $product->quantity = $request->{'quantity'};
                    $product->featured = $request->input('featured') ? 1 : 0;
                    $dproductb->save();
                    return 1;
                } catch (\Illuminate\Database\QueryException $ex) {
                    Log::channel('merchant_error')->error($ex);
                    return -1;
                }
            }
        }
}
Sudhanshu Kumar
  • 1,926
  • 1
  • 9
  • 21
  • your ajax code isn't even being used because you aren't suppressing the default submit behaviour of the button/form. But even if it was, you can't send files as JSON, because JSON is text. https://stackoverflow.com/questions/23980733/jquery-ajax-file-upload-php might help you. P.S. Maybe a bit more tutorial study in general would be beneficial. – ADyson Jan 13 '21 at 12:00
  • 1
    What is the error? and why are you not storing the image on you server in a directory? it's by default in temp directory – Sudhanshu Kumar Jan 13 '21 at 12:00
  • 1
    "the file is also not uploading tot the server"...your dd output appears to contradict this. It shows you exactly where the file is. So it definitely gets uploaded...the problem is more likely to be related to what you're doing with it after that. You didn't provide any info about error messages or the precise behaviour, though. Tell us what it _does_ do, as well as what it doesn't do. – ADyson Jan 13 '21 at 12:03
  • try using form data and pass processData false to your ajax. and pass type as POST – Aasif khan Jan 13 '21 at 12:46
  • Hi @ADyson thx for the tutorial link. What I am trying to do with the file is to save the filename into my database and upload into my specific folder in public along with the other form field datas on the create modal (which is a popout from my table button). And I realised the file is not uploaded into my directory as well apologies on that. – junmingyeo98 Jan 14 '21 at 02:07
  • This is the output of my error: [2021-01-13 10:02:42] local.ERROR: SQLSTATE[23502]: Not null violation: 7 ERROR: null value in column "prodImage" violates not-null constraint DETAIL: Failing row contains (134, 123, 213, null, null, 321, 123, 123, f, 2021-01-13 10:02:42, 2021-01-13 10:02:42, 3). – junmingyeo98 Jan 14 '21 at 02:11

1 Answers1

0

I have managed to made it work, however previously when I return a numerical value, it will pop out my javascript notification method but now it only returns the numerical value. What seems to be the issue here?

Below are my working create function for the new product:

public function create(Request $request)
    {
        if ($this->isCodeExist($request->{'prodCode'})) {
            return 0;
        } else {
            $product = Product::create($request->all());

            if ($request->hasFile('prodImage')) {
                $file = $request->file('prodImage');

                //Get file name with the time
                $name = time() . '_' . $file->getClientOriginalName();

                //Store file into public folder
                $file->move(public_path('img/products/'), $name);

                try {
                    //Insert ProdImage DB field with file name above
                    $product->prodImage = $name;
                    $product->save();
                    return 1; 
                    //back()->with('success_message', 'Product updated successfully!');
                } catch (\Illuminate\Database\QueryException $ex) {
                    Log::channel('merchant_error')->error($ex);
                    return -1;
                }
            }
        } 
    }

Below are my javascript to check for the ajax method for the fileupload and creation of new product:

 $('create_product').submit(function(event) {
        event.preventDefault();
        var formData = new FormData($(this)[0]);
            $.ajax({
                url: '{{ route('merchant.product.create') }}',
                type: 'POST',              
                data: formData,
                success: function(data) { 
                    if (data == 0) {
                        $('#new_productsave_btn').html( $('#new_productsave_btn').data('original-text')).prop('disabled', false);
                        showNotify("Product Code already exist", "error");
                        return;
                    } else if (data < 0) {
                        $('#new_productsave_btn').html( $('#new_productsave_btn').data('original-text')).prop('disabled', false);
                        showNotify("Something went wrong", "error");
                        return;
                    }
                    showNotify("New product has been added successfully", "success");
                    location.reload();
                },
                error: function(data) {
                    $('#new_productsave_btn').html( $('#new_productsave_btn').data('original-text')).prop('disabled', false);                        
                    console.log(data);
                    showNotify("Something went wrong", "error");
                }
            });

        });

Below is my notify js function:

function showNotify(msg, className) {
            $.notify(
                msg, 
                { 
                    globalPosition:"top right", 
                    className: className
                }
            );
        }