gitana / alpaca

Alpaca provides the easiest way to generate interactive HTML5 forms for web and mobile applications. It uses JSON Schema and simple Handlebars templates to generate great looking, dynamic user interfaces on top of Twitter Bootstrap, jQuery UI, jQuery Mobile and HTML5.
http://www.alpacajs.org
Other
1.29k stars 371 forks source link

Upload Field deleteUrl incorrect when populated from data #710

Open davidzof opened 5 years ago

davidzof commented 5 years ago

If you edit an existing form and pre-populate the Upload field from a files array the delete URL is always the last element in the array.

Looking at alpace.js.download the following code is used:-

var fileIndex = $(button).attr("data-file-index");
console.log("file index " + fileIndex);

fileIndex is always the last index in the array not the button that fired the event.

davidzof commented 5 years ago

in UploadField.js I made the following mods to handle both the case of a files data object and adding / deleting files.

In Alpaca.Fields.UploadField we now attached our onclick event to the delete button in the row, not the last instance of the button.

When the event is fired we recovered the file object using file index. However if we add new files there will be two file objects. So when we delete the file from the files array we need to compare deleteUrls and delete the appropriate row(s). Normally a deleteUrl will be unique.

Have not considered the case of object types... need to test with other alpaca File controls.

                    rows = $(rows);
                    $(rows).each(function(index, value) {
                        if (options.fileupload && options.fileupload.autoUpload) {
                            // disable start button
                            $(value).find("button.start").css("display", "none");
                        }

                        self.handleWrapRow(this, options);

                        // this event gets fired when fileimpl has cleaned up the DOM element
                        // we handle Ajax related stuff on our own here
            $(value).find("button.delete").on("click", function() {
                            var button = this
                            var fileIndex = $(button).attr("data-file-index");
                            var file = files[fileIndex];
                            self.onFileDelete.call(self, row, button, file);

            // remove from files
            $.each(self.data, function(index, item){
                    if (item.deleteUrl === file.deleteUrl) {
                      self.data.splice(index, 1);
                    }
            });
britisharmy commented 1 year ago

How did you manage to pre-populate the Upload field from a files array?

I have this object

{
    "files": [{
        "name": "713311.png",
        "size": false,
        "deleteUrl": "https://example.com/file_uploads/uploads/713311.png",
        "deleteType": "DELETE"
    }, {
        "name": "1008112.png",
        "size": false,
        "deleteUrl": "https://example.com/file_uploads/uploads/1008112.png",
        "deleteType": "DELETE"
    }, {
        "name": "1048333.png",
        "size": false,
        "deleteUrl": "https://example.com/file_uploads/uploads/1048333.png",
        "deleteType": "DELETE"
    }, {
        "name": "1768201.png",
        "size": false,
        "deleteUrl": "https://example.com/file_uploads/uploads/1768201.png",
        "deleteType": "DELETE"
    }],
    "name": "John Matrix",
    "age": 40,
    "images": "no images",
    "ice": "Mint",
    "condition": "Refurbished",
    "array_data": [{
        "flavor": "strawberry",
        "topping": "nuts"
    }, {
        "flavor": "chocolate",
        "topping": "raisin"
    }],
    "description_required": "Y",
    "printer_type": "Laser Jet",
    "description": "<p><strong>This is a very good description</strong></p>",
    "color": "Blue"
}

and using post render to populate the forms with my data


"postRender": function() {
$.get("http://localhost:8000/data_routes/fetch_edit_data", function(response){
form.data = response;
    console.log('Mounted Lifecycle Method', response );
    console.log('After Edit Data Inserted', form.data );
    let remoteData = JSON.parse(response);
    console.log('Remote Data', typeof response );
    //Object.assign(form.data, remoteData);
    $('#form').alpaca().setValue(remoteData);
  });

}

The images are not displaying.

davidzof commented 1 year ago

Hi Geoffrey, it is quite some time ago now since I worked on this.

I see you've opened a ticket. Are the images getting uploaded to the server? You'll need somethink like the servlet uploader example given by Alpaca. In that case Alpaca, Javascript creates a preview element like this:

<td class="preview">
            <a href="/library/images/Lvm/bQyD.jpg" title="Lvm/bQyD.jpg" data-gallery="gallery" download="Lvm/bQyD.jpg">
                <img src="/library/images/Lvm/thumb_bQyD.jpg">
            </a>
        </td>

In this case my uploader creates a thumbnail for the preview.

britisharmy commented 1 year ago

Thanks for your response. I have successfully managed to upload multiple images and the json returned looks like this

"files":[{"name":"3085330 (6).png","size":18693,"type":"image\/png","url":"https:\/\/example.com\/file_uploads\/files\/3085330%20%286%29.png","thumbnailUrl":"https:\/\/example.com\/file_uploads\/files\/thumbnail\/3085330%20%286%29.png","deleteUrl":"https:\/\/example.com\/file_uploads\/index.php?file=3085330%20%286%29.png","deleteType":"DELETE"}]

I also want to do that but hat would also mean writing code to handle deletes and merging arrays whenever a new or new images are added.