These are chat archives for canjs/canjs

29th
Sep 2017
Gregg Roemhildt
@roemhildtg
Sep 29 2017 14:21
Hi guys, is there a way to have can-fixture handle file uploads? I've got a fixture, that I'd like to access the file names but it seems that my form data object is being converted somewhere.
fixture({
    method: 'POST',
    url: '/upload'
}, function (request, response, headers, ajaxSettings) {
    console.log(request.data.entries()); // throws error TypeError: 'entries' called on an object that does not implement interface FormData.
    return {
        uploads: ['/path/to/file/fake_upload_filename']
    };
});
Jeroen Cornelissen
@jeroencornelissen
Sep 29 2017 14:26
What is in request.data ?
@roemhildtg I think request.data is just a plain object, and not your FormData DefineMap.
Gregg Roemhildt
@roemhildtg
Sep 29 2017 14:30
Hmm
So this is where the request gets created:
         const data = new FormData();
        for (let i = 0; i < files.length; i++) {
            data.append(i, files.item(i));
        }
        this.state = new Promise((resolve, reject) => {

            const req = new XMLHttpRequest();
            req.open('POST', this.properties.url, true);
            req.onload = function () {
                if (req.status === 200) {
                    resolve(JSON.parse(req.responseText));
                } else {
                    reject(req);
                }
            };
            req.onerror = reject;
            req.send(data);
image.png
This is the request object the fixture gets
Jeroen Cornelissen
@jeroencornelissen
Sep 29 2017 14:36
Then I don’t know :worried:
try req.send(data.serialize());
What is FormData?
I used FormData since it handles file uploads
It seemed to be the 'recommended' approach for submitting files via ajax
Jeroen Cornelissen
@jeroencornelissen
Sep 29 2017 14:38
Aah, I thought it was an extend of DefineMap
Gregg Roemhildt
@roemhildtg
Sep 29 2017 14:38
Yeah, sorry for not being more clear on that
Jeroen Cornelissen
@jeroencornelissen
Sep 29 2017 14:39
maybe: req.send(data.getAll());
getAll: Returns an array of all the values associated with a given key from within a FormData.
Gregg Roemhildt
@roemhildtg
Sep 29 2017 14:41
Well, I think the req.send part is correct. If I send data.getAll() it will probably break since req.send expects a FormData instance
Jeroen Cornelissen
@jeroencornelissen
Sep 29 2017 14:42
And if you do it in your fixture? request.data.getAll()
Gregg Roemhildt
@roemhildtg
Sep 29 2017 14:42
Oh, that throws the same error
...called on an object that does not implement interface FormData
Jeroen Cornelissen
@jeroencornelissen
Sep 29 2017 14:43
Then I’m really out of ideas...
Gregg Roemhildt
@roemhildtg
Sep 29 2017 14:44
No worries, thanks for having a look. Its good to know its not just me :wink:

ajaxSettings says

the data to XMLHTTPRequest.prototype.send is converted to a JavaScript objects

Is there anyway to turn that off?

Gregg Roemhildt
@roemhildtg
Sep 29 2017 15:07
I see the issue now. So the xhr data is automatically processed using can-assign. So the FormData object is converted to a plain object
Gregg Roemhildt
@roemhildtg
Sep 29 2017 15:23
I could submit a pull request to allow this. I'm thinking add a xhrSettings.processData option to allow the user (me) to disable can-fixture automatically processing the data
Chasen Le Hara
@chasenlehara
Sep 29 2017 15:32
Watch our LIVE contributors meeting where we’ll discuss the results of our community survey! https://www.youtube.com/watch?v=XWq2bwm-rjU
Chasen Le Hara
@chasenlehara
Sep 29 2017 17:52
Nico R.
@nriesco
Sep 29 2017 18:27

what is the correct way of re-writting this code:

https://github.com/donejs/place-my-order/blob/6d682fda40de255ffe453ecb5e04000d02309540/src/order/new/new.js#L17-L21

restaurant: {
  get(lastSetVal, resolve) {
    this.restaurantPromise.then(resolve);
  }
},

I tried this bud didn't work:

restaurant: {
  get(lastSetVal, resolve) {
    this.restaurantPromise.then(() => {return resolve;});
  }
},

I thought then(function) was the same as then(() => return function;) maybe the parameters are missing?

Thanks

I think I found a way:
restaurant: {
  get(lastSetVal, resolve) {
    this.restaurantPromise.then(params => { return resolve(params); });
  }
},
Gregg Roemhildt
@roemhildtg
Sep 29 2017 18:31
@nriesco the first way is correct. resolve is a function that sets the value.
Nico R.
@nriesco
Sep 29 2017 18:31
thanks @roemhildtg it does work and is correct, but I’m trying to re-write it so I can do other stuff
Gregg Roemhildt
@roemhildtg
Sep 29 2017 18:32
You could do this and it would be the same:
restaurant: {
  get(lastSetVal, resolve) {
    this.restaurantPromise.then(function(data) { 
        resolve(data); 
        // do other stuff
    });
  }
},
Nico R.
@nriesco
Sep 29 2017 18:32
@roemhildtg yes, that seems to work, only that params should be data instead
Gregg Roemhildt
@roemhildtg
Sep 29 2017 18:32
doesn't have to be.
You can call it whatever you prefer
Nico R.
@nriesco
Sep 29 2017 18:33
let me try
Gregg Roemhildt
@roemhildtg
Sep 29 2017 18:33
I had a typo
Nico R.
@nriesco
Sep 29 2017 18:33
that’s what I meant
thanks
it is very interesting to use this approach, this way I’ll be able to get the amount of results and other stuff
Gregg Roemhildt
@roemhildtg
Sep 29 2017 18:37
Right. You just need to make sure that restaurants is used somewhere in your view model or template so that it actually gets called
Nico R.
@nriesco
Sep 29 2017 18:38
as far as I understand there is no other way of getting the amount of results, so instead of just iterating over the values I can make decisions and handle pagination
that’s correct
in my case (I use feathersjs as API) i get both the DefineMap with the data as well as length, limit, skip and total
Gregg Roemhildt
@roemhildtg
Sep 29 2017 18:40
I use a custom behavior for can-connect to add this information
I use flask-restless which returns a total property.
Nico R.
@nriesco
Sep 29 2017 18:41
do you have any example on how to do that? it might be a better approach
as for my approach this is how my code looks like, you can decide how to deal with the information this way:
mainModelValue: {
  get: function(last, set) {
    if (this.promiseValue) {
      this.mainModelPromise
        .then(data => {
          console.log('Query result information:', data);
          return set(data);
        });
    } else {
      this.mainModelPromise.then(set);
    }
  }
},
Gregg Roemhildt
@roemhildtg
Sep 29 2017 18:43
Well, I'm not really sure if I did this the correct way either but I can share it. one sec
I'm just setting it in a property on the connection.metadata object I created.
It should really be on the List property, but I wasn't really sure how or where to put it at the time
In my case, I use server side pagination, so the number of objects that the connection gets is not the total number of objects available on the server.
And flask-restlesss returns a total which has this number, and I set it on the metadata so I can paginate