vue-mc icon indicating copy to clipboard operation
vue-mc copied to clipboard

Collection fetch with queries

Open mrFANRA opened this issue 6 years ago • 14 comments

Im not understand in documentation, how can I fetch data by collection class with queries?

var offers = new OffersCollection(); offers.page(1).fetch(() => {}); //Request with page sent, models in collection exist.

But how I can add dynamic parameters, for example: "...&param1=123&param2=321"?

mrFANRA avatar Feb 04 '18 23:02 mrFANRA

See http://vuemc.io/#collection-attributes

rtheunissen avatar Feb 05 '18 03:02 rtheunissen

Model

export default class OffersCollection extends CollectionBase{
    model(){
        return OfferModel;
    }

    defaults() {
        return {
            param: '123',
        }
    }

    routes() {
        return {
            fetch:  '/offers',
        }
    }
}

Usage:

this.offers = new OffersCollection();
this.offers.fetch(() => {});

Request is going without param. What I make wrong?

mrFANRA avatar Feb 05 '18 06:02 mrFANRA

Sorry for taking so long on this @mrFANRA. Attributes are included as route parameters rather than query parameters. For example, /my/route/to/resource/{id} would use the id attribute of the collection.

rtheunissen avatar Apr 19 '18 22:04 rtheunissen

You can override getFetchQuery in your base collection to return attributes, if you want. In a future release it makes sense to fall back to query parameters if the route doesn't have a placeholder for the attribute. I'll leave this open until that is implemented.

rtheunissen avatar Apr 19 '18 22:04 rtheunissen

so, I understand correctly it's not possible to add query-parameters??

haayman avatar Jul 03 '18 09:07 haayman

You can if you override base class and update the fetch function like that :

    /**
     * Fetches data from the database/API.
     *
     * @param {options}             Fetch options
     * @param {options.params}      Query params
     * @param {options.headers}     Query headers
     * @returns {Promise}
     */
    fetch(options = {}) {
        const config = () => ({
            url     : this.getFetchURL(),
            method  : this.getFetchMethod(),
            params  : assign({}, this.getFetchQuery(), options.params),
            headers : assign({}, this.getFetchHeaders(), options.headers),
        });

        return this.request(
            config,
            this.onFetch,
            this.onFetchSuccess,
            this.onFetchFailure
        );
    }

After that You can use fetcj to oferride params, headers, ... :

this.collection.page(1).fetch({
    params : {
        param1 : "test",
        // ...
    }
});

I make pull request with this modifications : #63

throrin19 avatar Aug 02 '18 08:08 throrin19

@haayman with the last version you can use custom params and headers in every query (fetch, save and delete)

throrin19 avatar Oct 09 '18 07:10 throrin19

This will be released as 0.4 soon, will notify.

rtheunissen avatar Oct 10 '18 16:10 rtheunissen

Released as 0.4

You can now specify:

this.collection.page(1).fetch({
    params : {
        param1 : "test",
        // ...
    }
});

rtheunissen avatar Oct 18 '18 17:10 rtheunissen

Unfortunately the parameters don't get properly converted to query-string. If I call the api using: params: { include: ["tickets"], order: [["createdAt", "ASC"]] }

the backend receives it as: params: { include: ["tickets"], order: [ '["createdAt", "ASC"]' // so, it's a string, not an array ] } So anything 2 levels deep isn't encoded properly

haayman avatar Oct 28 '18 19:10 haayman

@haayman the backend format is normal. You have to parse this in backend to correctly convert your data.

The QueryParams only used first array level. If you want more complex level, you need to convert this using an external lib (like bodyParser for body part)

throrin19 avatar Nov 05 '18 10:11 throrin19

@haayman the backend format is normal. You have to parse this in backend to correctly convert your data.

The QueryParams only used first array level. If you want more complex level, you need to convert this using an external lib (like bodyParser for body part)

Hi @throrin19 Can you explain how to implement/override Base class to support a complex params?
In my case, backend receive params as filters array, so I need to pass the object {filters: { key1: val, key2: val }}, and query string must be ?filters[key1]=val&filters[key2]=val, actually returns ?filters[Object_Object] I want to returns this method to create the query params:

export const buildParams = (
  prefix: string | number,
  val: any[] | Record<string, any>,
  top = true
): string => {
  if (_.isArray(val)) {
    return _.map(val, function(value, key) {
      return buildParams(top ? key : prefix + "[]", value, false);
    }).join("&");
  } else if (_.isObject(val)) {
    return _.map(val, function(value, key) {
      return buildParams(top ? key : prefix + "[" + key + "]", value, false);
    }).join("&");
  } else {
    return encodeURIComponent(prefix) + "=" + encodeURIComponent(val);
  }
};

I try to override getRouteParameters but I need to returns a type Record<string, any>, not only string:

  getRouteParameters(): string {
    const obRouteParams = super.getRouteParameters();
    return _.isString(obRouteParams)
      ? obRouteParams
      : buildParams("", obRouteParams);
  }

Thanks

alvaro-canepa avatar Oct 19 '20 08:10 alvaro-canepa

@alvaro-canepa vue-mc use axios to send request. Look directly with them to know how to do that

throrin19 avatar Oct 19 '20 09:10 throrin19

Hi @throrin19 Sorry, the issue was on laroute plugin The solution was very easy with a custom script.

Thanks

alvaro-canepa avatar Oct 19 '20 09:10 alvaro-canepa