Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cannot modify the fileRecord in upload handler #53

Closed
jigarzon opened this issue Apr 14, 2020 · 10 comments
Closed

Cannot modify the fileRecord in upload handler #53

jigarzon opened this issue Apr 14, 2020 · 10 comments

Comments

@jigarzon
Copy link

jigarzon commented Apr 14, 2020

Hi, after uploading, I need to update the url property in the fileRecord object, in order to store in my database the fileRecord with all the information needed to see the files later (as commented in the section "Demo 1. Preloading Existing Files" of the documentation).

I try to modify the fileRecord object in this way:

uploaded(ev) {
      var files = Array.isArray(ev) ? ev : [ev]
      for (var file of files) {
        var respObj = JSON.parse(file.request.response)
        var backendResponse = respObj.result.files.file[0]   //this is the way my backend returns it
        if (fileObj) {
          file.fileRecord.url = backendResponse.url
        }
        
      }
    },

The problem is that after modifying the fileRecord, it's not reflected in the v-model instance (the files have no url set)
I even tried to make something more complex: finding the specific file in the model and updating it manually... but it still doesn't work:

 uploaded(ev) {
      var files = Array.isArray(ev) ? ev : [ev]
      for (var file of files) {
        var respObj = JSON.parse(file.request.response)
        var backendResponse = respObj.result.files.file[0]
        var fileRecord = this.fileRecords.find(
          f => f.upload.data.result.files.file[0].name === backendResponse.name
        )
        if (fileRecord) {
          fileRecord.url =backendResponse.url
        }
      }

    },

What is the common way of resolving this?

@safrazik
Copy link
Owner

safrazik commented Apr 14, 2020

the reactive (i.e: reflected in the v-model instance) properties of fileRecord are converted into functions from primitive values. The only supported reactive properties at the moment are:
(when called without argument, it's a getter, otherwise setter.

{
  progress: 0,
  name: 'Some name.txt'
  // ...
}
  • fileRecord.progress(value?: number) - get/set upload progress
  • fileRecord.name() - get file name (readonly)

As your use makes a lot of sense, maybe url should be changed to a reactive property as well.

What is the common way of resolving this?

The ideal solution would be (after implementing fileRecord.url() reactive property)

 uploaded(event) {
      var responses = Array.isArray(event) ? event : [event]
      for (var response of responses) {
        var respObj = response.data
        var backendResponse = respObj.result.files.file[0] //this is the way my backend returns it
        var fileRecord = response.fileRecord
        fileRecord.url(backendResponse.url)
      }
  },

Workaround for now:

 uploaded(event) {
      var responses = Array.isArray(event) ? event : [event]
      for (var response of responses) {
        var respObj = response.data
        var backendResponse = respObj.result.files.file[0] //this is the way my backend returns it
        var fileRecord = response.fileRecord
        var index = this.fileRecords.indexOf(fileRecord);
        // for re-calculation
        this.fileRecords[index] = {
          name: fileRecord.name,
          // ...
          url: backendResponse.url,
        }
      }
  },

@jigarzon
Copy link
Author

I've tried that but it's still not reactive.

@jigarzon
Copy link
Author

This is the exact code I'm using:

  uploaded (ev) {
      var files = Array.isArray(ev) ? ev : [ev]
      for (var file of files) {
        var respObj = JSON.parse(file.request.response)
        var backendResponse = respObj.result.files.file[0]
        var fileRecord = file.fileRecord
        var index = this.fileRecords.indexOf(fileRecord)
        this.fileRecords[index] = {
          name: fileRecord.name,
          url:  backendResponse.url
        }
      }
    },

@safrazik
Copy link
Owner

You have to fill other props as well

        this.fileRecords[index] = {
          name: fileRecord.name,
          // ... other props!
          url: backendResponse.url,
        }

@safrazik
Copy link
Owner

The required props for preloading:

{
            "name":"Some.exe",
            "size": 8165824,
            "type": "application/vnd.microsoft.portable-executable",
            "ext":"exe",
}

@jigarzon
Copy link
Author

Thanks a lot safrazik for your help & time.

I did that update:

 uploaded (ev) {
      var files = Array.isArray(ev) ? ev : [ev]
      for (var file of files) {
        var respObj = JSON.parse(file.request.response)
        var backendObj = respObj.result.files.file[0]
        var fileRecord = file.fileRecord
        var index = this.fileRecords.indexOf(fileRecord)
        this.fileRecords[index] = {
          name: fileRecord.name,
          size: fileRecord.size,
          type: fileRecord.type,
          ext: fileRecord.ext,
          url: backendObj.url
        }
      }
    },

But I still see this in my model (I made a simple {{fileRecords}} in my component to see its value):

[ { "file": {}, "url": null, "urlResized": null, "lastModified": 1581000145000, "sizeText": "97 KB", "size": 99161, "type": "image/png", "ext": "png", "color": "transparent", "upload": { "data": { "result": { "files": { "file": [ { "container": "1", "name": "4348731801885217.png", "type": "image/png", "field": "file", "originalFilename": "profile1.png", "size": 99161 } ] }, "fields": { "filename": [ "profile1.png" ] } } }, "error": false }, "dimensions": { "width": 360, "height": 261 } } ] 

@safrazik
Copy link
Owner

 uploaded (ev) {
      var files = Array.isArray(ev) ? ev : [ev]
      for (var file of files) {
        var respObj = JSON.parse(file.request.response)
        var backendObj = respObj.result.files.file[0]
        var fileRecord = file.fileRecord
        var index = this.fileRecords.indexOf(fileRecord)
        this.fileRecords[index] = {
          name: fileRecord.name,
          size: fileRecord.size,
          type: fileRecord.type,
          ext: fileRecord.ext,
          progress: 100,
          url: backendObj.url
        }
      }
      this.fileRecords = this.fileRecords.slice() // trigger vue change
    },

Note that it's still a hack only

@jigarzon
Copy link
Author

Thanks its too hacky, I will workaround in a different way. I will encaspulate everything in a component with computed get / set to emit the right value to the parent.

I would let this ticket open, if you like, to require for a better way to resolve this case, as this is an open issue in a bunch of tickets I saw.

I really appreciate this project, its an awesome solution fully of features and looks great... its not easy to find such powerful components in standalone efforts in the Vue ecosystem .

@safrazik
Copy link
Owner

You can wait for the fix to arrive in few days.

Thanks for the appreciation. Thanks for using the library.

@safrazik
Copy link
Owner

fileRecord.url() is a reactive property from versoin 1.7.0-beta.0

 uploaded(event) {
      var responses = Array.isArray(event) ? event : [event]
      for (var response of responses) {
        var respObj = response.data
        var backendResponse = respObj.result.files.file[0] //this is the way my backend returns it
        var fileRecord = response.fileRecord
        fileRecord.url(backendResponse.url)
      }
  },

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants