0

I'm trying to make a ajax call in admin page to upload a csv file in directory then to make a stock update function.

In my PHTML:

<form method="post" enctype="multipart/form-data" id="ajaxCall" >
<input name="form_key"  type="hidden" value="<?php /* @escapeNotVerified */ echo $block->getFormKey() ?>"  />
<span class="file-uploader-button action-default">Upload CSV file:</span> <input id="image_to_upload" type="file" name="file" required />
<br/>
<input type="submit" id="import"/>
</form>
<script>

require([
    "jquery"
], function ($) {
     //your code to send ajax request here
     $.noConflict();    
    formdata = new FormData();      
    $("#image_to_upload").on("change", function() {
        alert("hello")
        var file = this.files[0];
        if (formdata) {
            formdata.append("image", file);
            $.ajax({
                url: "admin/grid/index/index",
                type: "POST",
                data: {dat:formdata,form_key: window.FORM_KEY},

                success:function(request){
                    console.log("success",request)
                },
                error:function (request, status, error) {
                    alert(request.responseText);
                }
            });
        }                       
    });   
});

</script>

When I click trigger this function I get below error.

jquery.js:10079 Uncaught TypeError: Illegal invocation

I have this script in the phtml which belongs to the same controller where I post using ajax because I have to show product update progress in the same page. In that controller I will get data like below if ajax works fine. Please note this is the previous working code in my phtml. I want to edit this code for controller standards.

<?php 
    $objectManager = \Magento\Framework\App\ObjectManager::getInstance ();
    $fileSystem = $objectManager->create('\Magento\Framework\Filesystem');
    $mediaPath = $fileSystem->getDirectoryRead(\Magento\Framework\App\Filesystem\DirectoryList::MEDIA)->getAbsolutePath();
    $stockRegistry = $objectManager->create('Magento\CatalogInventory\Api\StockRegistryInterface');
    $product = $objectManager->get('Magento\Catalog\Model\Product');
if(isset($_POST['submit'])){
    if (!file_exists($mediaPath.'csv')) {
        mkdir($mediaPath.'csv', 0777, true);
    }
    $file_type = $_FILES['file']['type']; //returns the mimetype
    $allowed = array('text/csv');
    if(!in_array($file_type, $allowed)) {?>
    <h1 class="error">Only CSV files allowed</h1>
    <tr>
        <td>Wrong format</td>
        <td>Wrong format</td>
        <td>Wrong format</td>
    </tr>
    <?php
    }else{    
    $displayFlag = 1;
    $csv =  $_FILES['file'];    
    $targetdir = $mediaPath;   
    $image_name=$_FILES['file']['name'];
    $temp = explode(".", $image_name);
    $newfilename = round(microtime(true)) . '.' . end($temp);
    $imagepath=$mediaPath."csv/".$image_name;
    if(move_uploaded_file($_FILES["file"]["tmp_name"],$imagepath)){
        $csvFile = file($imagepath);
        $data = [];
        foreach ($csvFile as $line) {
            $data[] = str_getcsv($line, ",", '"');
        }
        var_dump( count($data));
        $keys = [];
        $result = [];
        foreach($data as $key => $value){
            if($key == 0){
                $keys = $value;
            }            
        }
        foreach($data as $key => $value){
            if($key !== 0){
                $result[] = array_combine($keys, $value);
            }            
        }
        foreach($result as $key => $value){
            if($product->getIdBySku($value['sku'])) {
                $stockItem = $stockRegistry->getStockItemBySku($value['sku']);
                $stockItem->setQty($value['qty']);
                $sku = $value['sku'];            
                if($stockRegistry->updateStockItemBySku($sku, $stockItem)){                
                    ?>
                    <tr>
                        <td><?php echo $value['sku'] ?></td>
                        <td><?php echo $value['qty'] ?></td>
                        <td>Updated</td>
                    </tr>
                <?php
                }else{?>
                    <tr>
                        <td><?php echo $value['sku'] ?></td>
                        <td><?php echo $value['qty'] ?></td>
                        <td>Updated</td>
                    </tr>
                    <?php
                }
            }else{ ?>
                 <tr>
                        <td><?php echo $value['sku'] ?></td>
                        <td><?php echo $value['qty'] ?></td>
                        <td>Sku Not found</td>
                    </tr>
            <?php
            }
        }
    }
}
}
?>
</table>
3
  • 1
    Utilise magento ui form components? github.com/DominicWatts/CsvUpload – Dominic Xigen May 30 '20 at 22:55
  • This module is great. But when I import I get this error 1 exception(s): Exception #0 (Magento\Framework\Exception\LocalizedException): The XML in file "/var/www/html/magento/app/code/Xigen/CsvUpload/view/adminhtml/ui_component/xigen_csvupload_csv_listing.xml" is invalid: Element 'argument': This element is not expected. Expected is ( dataProvider ). Line: 16 – Ramesh KR May 31 '20 at 5:16
  • That error would suggest I've gone wrong in the XML somewhere. It's been a while since I've used this on a project. Please log an issue on github and that will remind me to take a look. – Dominic Xigen May 31 '20 at 9:27
0

I would suggest not trying to re-invent the wheel and to try leveraging the file uploader UI component.

Devdocs includes some examples you can follow:

https://devdocs.magento.com/guides/v2.3/ui_comp_guide/components/ui-fileuploader.html#example

If you implement this as a UI Component, you won't need to worry about moving business logic out of the PHTML, because it will be moved into the JS.

You can extend the "onFileUploaded" event like this:

define([
'Magento_Ui/js/form/element/file-uploader'
], function (Element) {
    'use strict';

    return Element.extend({
        defaults: {
            fileInputName: ''
        },

        /**
         * Handler of the file upload complete event.
         *
         * @param {Event} e
         * @param {Object} data
         */
        onFileUploaded: function (e, data) {
            this._super(e, data);
            //Do whatever you want here, including sending async javascript requests
        }
    });
});

Switching to the UI Component implementation will not only be easier in the long run, but it will encourage you to write the implementation correctly and fix the numerous code problems seen in the posted code (you shouldn't use ObjectManager directly and files / folders should never be 777). PHTML should have very little PHP code, etc...

2
  • could you please elaborate I need to trigger a php function using phtml – Ramesh KR May 31 '20 at 5:16
  • not sure if you saw but I did update my answer. – Shapeshifter Jun 3 '20 at 12:54

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.