eggplantSword's avatar

Sending data back and forth from controller to vue

I'm trying to create a products store, and I'm trying to set up an active filters/categories search but when I send the category ids back and forth they convert to string and the search crashes. I can't get it to work correctly.

This is my vue code

setCategory(val) {
    this.category = val;

    if (!this.active_filters.includes(parseInt(val))) {
        this.active_filters.push(parseInt(val))
    }

    this.getProducts();
},
getProducts() {
    var context = this;

    axios.get(`${url}` + 'products/data?pagination%5Bpage%5D=' + context.page + '&pagination%5Bpages%5D=' + context.pages + '&pagination%5Bper_page%5D=' + context.per_page + '&pagination%5Btotal%5D=' + context.total + '&sort%5Bfield%5D=' + context.sort_field + '&sort%5Bsort%5D=' + context.sort_direction + '&query%5Bcategory%5D=' + context.category +  '&query%5Bbrand%5D=' + context.brand + '&query%5Bactive%5D=' + context.active_filters)
                .then((resp) => {
                    console.log(resp.data);
                    context.products = resp.data.products;
                    context.categories = resp.data.categories;
                    context.brands = resp.data.brand;
                    context.page = resp.data.page;
                    context.pages = resp.data.pages;
                    context.per_page = resp.data.per_page;
                    context.total = resp.data.total;
                    context.sort_direction = resp.data.sort;
                    context.sort_field = resp.data.field;
                });
        },

Controller method

function getProductsStore(Request $request)
    {
        $brands = Brand::withCount('products')->get();

        $active_categories = [];

        if ($request['query']['active'] !== null) {
            array_push($active_categories, intval($request['query']['active']));
        }

        if (!empty($active_categories)) {
            $categories = Category::whereIn('category_id', $active_categories)
                ->with('childrenRecursive')
                ->withCount('products', 'children')
                ->get();
        } else {
            $categories = Category::with('childrenRecursive')
                ->withCount('products', 'children')
                ->whereNull('category_id')
                ->get();
        }

        $pagination = $request->query('pagination');
        $prod = Product::where('is_active', true)
            ->with(['categories', 'brand', 'images' => function ($query) {
                $query->where('default', true);
            }])
            ->Order($request)
            ->BrandStore($request)
            ->CategoryStore($request)
            ->paginate($request['pagination']['per_page'], ['*'], 'page', $pagination['page']);


        return response()->json([
            "products" => $prod->toArray()['data'],
            "categories" => $categories,
            "brand" => $brands,
            "page" => $prod->currentPage(),
            "pages" => $prod->lastPage(),
            "per_page" => $request['pagination']['per_page'],
            "total" => $prod->total(),
            "sort" => "asc",
            "field" => "product"
        ]);
    }

Product Model

    function scopeCategoryStore($query, $request)
    {
        if ($request['query'] && $request["query"]["active"] != null) {
            $query->whereHas('categories', function ($q) use ($request) {
                $q->whereIn('category_id', $request["query"]["active"]);
            });
        }
    }

What I'm trying to do is take the active filters and find the products that have those categories.

I get an error from the scope in the product model

Argument 1 passed to Illuminate\Database\Query\Builder::cleanBindings() must be of the type array, string given,

on this line

function scopeCategoryStore($query, $request)
    {
        if ($request['query'] && $request["query"]["active"] != null) {
            $query->whereHas('categories', function ($q) use ($request) {
//this line here
                $q->whereIn('category_id', $request["query"]["active"]);
            });
        }
    }

I'm not sure what I'm doing wrong or how to fix this.

0 likes
1 reply
piljac1's avatar

The problem is that you're building an array and then appending that array to your active query string key. That means that if you have an array that looks like [1, 2, 3], it will be converted to a 1,2,3 string. Then on the backend, you get the active key from your query string, and you get a string containing 1,2,3 instead of an array.

What you need to do is send something like this to receive an array on the backend: &query[active][]=1&&query[active][]=2&query[active][]=3.

An even easier and cleaner way would be the following syntax (which would solve your problem by automatically using the right query string syntax for arrays). However, if you want to use that syntax, you will need to use and import the qs library to stringify your data (see here).

axios.get(url, {
  params: {
    pagination: {
      page: context.page,
      pages: context.pages,
      per_page: context.per_page,
      total: context.total
    },
    sort: {
      field: context.sort_field,
      sort: context.sort_direction
    },
    query: {
      category: context.category,
      brand: context.brand,
      active: context.active_filters
    }
  },
  paramsSerializer: params => (
    qs.stringify(params)
  )
})
  .then((resp) => {
    console.log(resp.data);
    context.products = resp.data.products;
    context.categories = resp.data.categories;
    context.brands = resp.data.brand;
    context.page = resp.data.page;
    context.pages = resp.data.pages;
    context.per_page = resp.data.per_page;
    context.total = resp.data.total;
    context.sort_direction = resp.data.sort;
    context.sort_field = resp.data.field;
  });

However, if you don't want to use a query string serialization library, you can limit the deep nesting to one level, which would give you what you want:

axios.get(url, {
  params: {
    'pagination[page]': context.page,
    'pagination[pages]': context.pages,
    'pagination[per_page]': context.per_page,
    'pagination[total]': context.total,
    'sort[field]': context.sort_field,
    'sort[sort]': context.sort_direction,
    'query[category]': context.category,
    'query[brand]': context.brand,
    'query[active]': context.active_filters
  }
})
  .then((resp) => {
    console.log(resp.data);
    context.products = resp.data.products;
    context.categories = resp.data.categories;
    context.brands = resp.data.brand;
    context.page = resp.data.page;
    context.pages = resp.data.pages;
    context.per_page = resp.data.per_page;
    context.total = resp.data.total;
    context.sort_direction = resp.data.sort;
    context.sort_field = resp.data.field;
  });

Please or to participate in this conversation.