Editor - Upload file (Handling aJax)

Editor - Upload file (Handling aJax)

ZakInterDevZakInterDev Posts: 51Questions: 16Answers: 0
edited May 2016 in Editor

Hi there

As the title suggests, I'm trying to upload a file and handle the aJax response myself. Following this https://editor.datatables.net/reference/field/upload guide, I see it gives the option to specify my ajax option. Also tried with a jQuery ajax object, but no luck even hitting the URL there

I've currently got

{
    label: "CSV:",
    name: "bulk_csv",
    type: "upload",
    ajax: {
        type: "POST",
        url: "/bulk_upload",
        done: function (json) {
            //Make your callback here.
            console.log(json);
        }
    }
}

as a field in my Editor instance.

Any ideas, or is it even possible?

Thanks in advance

Answers

  • allanallan Posts: 61,805Questions: 1Answers: 10,119 Site admin

    Yes it is quite possible and what you have above looks like it should actually work. Are you getting any errors shown in your browser's console? Are you using 1.5.5?

    Do you have a link to the page so I can debug it live please?

    Allan

  • ZakInterDevZakInterDev Posts: 51Questions: 16Answers: 0

    Getting a console error

    Uncaught TypeError: Cannot read property 'id' of undefined -> dataTables.editor.min.js:57 
    

    Using Editor v1.5.1 is there a bug in this version that I'm unaware of?

    I'll look into a test page, if the above doesn't help out

  • ZakInterDevZakInterDev Posts: 51Questions: 16Answers: 0

    Just upgraded to v1.5.5, no longer getting the console error but i'm getting a "A server error occurred while uploading the file" as a DataTables error. I assume this is a default response since I'm trying to override it.

    The console log in my 'done' function doesn't appear either.

  • ZakInterDevZakInterDev Posts: 51Questions: 16Answers: 0
    edited May 2016

    After a bit further investigation into dataTables.editor.js I see the "Editor.upload" function has it's own success & error handling functions....and looks like these aren't overwritten by my one (If I change "done" to "success" for example)

    Edit:
    I can confirm by commenting out this code in the dataTables.editor.js file

    success: function ( json ) {
                    editor.off( 'preSubmit.DTE_Upload' );
    
                    if ( json.fieldErrors && json.fieldErrors.length ) {
                        var errors = json.fieldErrors;
    
                        for ( var i=0, ien=errors.length ; i<ien ; i++ ) {
                            editor.error( errors[i].name, errors[i].status );
                        }
                    }
                    else if ( json.error ) {
                        editor.error( json.error );
                    }
                    else if ( ! json.upload || ! json.upload.id ) {
                        editor.error( conf.name, generalError );
                    }
                    else {
                        if ( json.files ) {
                            $.each( json.files, function ( name, value ) {
                                Editor.files[ name ] = value;
                            } );
                        }
    
                        ids.push( json.upload.id );
    
                        if ( counter < files.length-1 ) {
                            counter++;
                            reader.readAsDataURL( files[counter] );
                        }
                        else {
                            completeCallback.call( editor, ids );
                            
                            if ( submit ) {
                                editor.submit();
                            }
                        }
                    }
                },
                error: function () {
                    editor.error( conf.name, generalError );
                }
    

    I was able to use my success function

    Would this be something you'd be looking into changing, over writing the callbacks of success & error

  • allanallan Posts: 61,805Questions: 1Answers: 10,119 Site admin

    Hi,

    Thanks for your investigation. I had thought that your done would actually be executed since I don't use that in Editor - it sounds like that is not the case.

    The problem with allowing success to be overwritten is that you need to provide all of the same logic as it implements. Do you actually need to do that, or do you just want to be informed when an upload is complete?

    If the latter, then listen for the upload.editor event of the upload field type. That will let you know when the upload is done.

    Allan

  • ZakInterDevZakInterDev Posts: 51Questions: 16Answers: 0
    edited May 2016

    Yeah the done function didn't execute.

    I don't personally need it. I'm using this upload feature to upload a bunch of barcodes, validate them and return a json list for select2. On the success, I automatically tag them into the list for the user. So they don't have to scan them individually.

    The problem with listening for the event, is having to respond with what your success function is expecting. I think it would be better for us to over write it if we wish, or somehow add to the function...(not sure if this is possible, I don't know all of Javascripts capabilities). Unless you can provide the JSON that is expected, similar to how you've done on https://editor.datatables.net/manual/server

    It looks to be like just the ID is required, but I'd like to confirm with you. Also I don't really need to keep this file I'm uploading, as it's just used to populate the select2 field. So going back to what I've said previously, I'd prefer to override the success function :)

    Thanks

  • allanallan Posts: 61,805Questions: 1Answers: 10,119 Site admin

    The problem with listening for the event, is having to respond with what your success function is expecting.

    The point of the event is that you don't need to respond to the success function at all - its already done for you. If you replaced the success function then that is where I think it would get messy.

    Unless you can provide the JSON that is expected, similar to how you've done on

    Good point - I really need to add that to the documentation! In the meantime, this is the structure:

    {
        "files": {
            "TABLENAME": {
                "ID": DATAOBJECT
            }
        },
        "upload": {
            "id": "ID"
        }
    }
    

    where:

    • TABLENAME is the table name used to store the file information in the db
    • ID is the file id
    • DATAOBJECT is the information for the file from the db

    The ID in the upload object should be the id of the newly uploaded file. All files in the table must currently be returned.

    Allan

  • ZakInterDevZakInterDev Posts: 51Questions: 16Answers: 0

    Ok, I'll give it ago! Sounds like it should work. Will post my solution here if it works, in case anyone else is planning on doing the same. Unfortunately other work has popped up, but will try get around to it asap. Thanks for the JSON :)

  • ZakInterDevZakInterDev Posts: 51Questions: 16Answers: 0
    edited May 2016

    Ok so few problems. First off this is the JSON I'm now returning.

    return response()->json([
                    [
                        "files" => [
                            "TABLENAME" => [
                                "ID" => [
                                    "id" => 1000,
                                    "filename" => "example_file_name.csv",
                                    "fileSize" => 500
                                ]
                            ]
                        ],
                        "upload" => [
                            "id" => 9999
                        ]
                    ]
        ]);
    

    I just threw in temp data, as the actual file getting uploaded doesn't matter. As I'm just trying to fool the uploads success function into thinking everything is A-OKAY! ...but that's failing as I'm still getting the error A server error occurred while uploading the file

    I also noticed the event 'upload.editor' only has the event object and value (Primary key) passed to it. This wouldn't work for me as I'm returning a list for my select2 field. I'd need to access all of the JSON returned by the server.

    Any thoughts? :)

    p.s.
    I'm assuming my "DATAOBJECT" as correct, as per https://editor.datatables.net/manual/php/upload

    p.p.s.
    I put some console logs in. One in the event, one before the ajax starts in dataTables.editor.js and another in the success function. They also execute in that order. So I feel it would be impossible to get the JSON response?

  • allanallan Posts: 61,805Questions: 1Answers: 10,119 Site admin

    A server error occurred while uploading the file

    That suggests that invalid JSON was returned. If you use your browser's network inspector tools, what exactly was returned?

    Your DATAOBJECT looks good. I presume you have changed TABLENAME and ID to be the table name and the id of the file?

    Allan

  • ZakInterDevZakInterDev Posts: 51Questions: 16Answers: 0
    edited May 2016
    {  
       "files":{  
          "TABLENAME":{  
             "ID":{  
                "id":1000,
                "filename":"bulk_barcodes_100.csv",
                "fileSize":500
             }
          }
       },
       "upload":{  
          "id":9999
       }
    }
    

    This is the JSON being returned. I haven't changed those keys as I don't actually have a table to store this data, because it doesn't need storing. The file being uploaded is simply used to fill the select2 field, making the file useless once this has been done. So I assume these keys/fields can be dummy data?

    To give you more of an inside look into what I'm trying to do. This is my serverside function, handling the upload.

    public function bulkUpload() {
            $select2_arr = [];
            if (Input::hasFile('csv_file')) {
                $file = Input::file('csv_file');
                if (($handle = fopen($file->getRealPath(), 'r')) !== false) {
                    while (($row = fgetcsv($handle, 1000, ",")) !== false) {
                        $barcode = $row[0];
                        $select2_arr[] = ["id" => $barcode, "text" => $barcode];
                    }
                    fclose($handle);
                }
            } else {
                return response()->json(array('error' => "File not found"));
            }
            return response()->json([
                        [
                            "files" => [
                                "TABLENAME" => [
                                    "ID" => [
                                        "id" => 1000,
                                        "filename" => "example_file_name.csv",
                                        "fileSize" => 500
                                    ]
                                ]
                            ],
                            "upload" => [
                                "id" => 9999
                            ]
                        ]
            ]);
        }
    

    So I'm looking to return the $select2_arr variable....but first I'm just trying to get this to work without adding that into the JSON

This discussion has been closed.