简体   繁体   中英

VueJS get unique values from array of objects based on key in watch

I have a watch to check the selected tags:

watch: {
  search (val) {
    for (let i = 0; i < val.length; i++) {
      this.form_data.products_credit.push({
        product_id: val[i].id,
        quantity: null,
        package_size: null,
        purchase_price: null,
        warehouse_id: null
      });
    }
  }
}

This works fine but the problem when the user select for example tag1 then this.form_data.products_credit value is equal to:

[
  {
    product_id: 1,
    quantity: null,
    package_size: null,
    purchase_price: null,
    warehouse_id: null
  }
]

After that if the user selected tag2 then this.form_data.products_credit result will be:

[
      {
        product_id: 1,
        quantity: null,
        package_size: null,
        purchase_price: null,
        warehouse_id: null
      },
      {
        product_id: 2,
        quantity: null,
        package_size: null,
        purchase_price: null,
        warehouse_id: null
      },
      {
        product_id: 2,
        quantity: null,
        package_size: null,
        purchase_price: null,
        warehouse_id: null
      }
    ]

What I am expecting:

I was not expecting the duplicated that happened after selecting another tag but that is normal since I am looping throw them.

What I have done:

I have tried to empty my products_credit before the loop like this:

this.form_data.products_credit = []

before the loop.

It worked fine but I don't want it that way because it will has side-effects on my next step.

A working example of the problem: here

You can check your array does not already contains your product before adding it :

watch: {
  search (val) {
    for (let i = 0; i < val.length; i++) {
      if (
        !this.form_data.products_credit.some(item => {
          item.product_id === val[i].id
        })
      ) {
        this.form_data.products_credit.push({
          product_id: val[i].id,
          quantity: null,
          package_size: null,
          purchase_price: null,
          warehouse_id: null
        });
      }
    }
  }
}

But I feel like there are much simpler and quicker solutions to your problem with computed properties based on an array of tags generated by a user's input . If you are able to share more of what you are doing, maybe we can find a better solution.

Edit : After seeing your JSFiddle, here is a proposition to handle your problem using only a computed property ( JSFiddle ) :

data: {
  search: [],
  products: [
    {
      id: 1,
      title: "first product",
      category: "first category",
      image: "first_image.jpg",
      barcode: "123123123"
    },
    {
      id: 2,
      title: "second product",
      category: "second category",
      image: "second_image.jpg",
      barcode: "23232323"
    },
  ],
  form_data: {
    category: null,
    products_credit: [],
  }
},
methods: {
    searchProducts (query) {
        //
    }
},
computed : {
  selectedProduct () {
    return this.search.map(item => {
      return {
        product_id: item.id,
        quantity: null,
        package_size: null,
        purchase_price: null,
        warehouse_id: null
      }
    })
  }
}

This is a preferred way to do this because the code is shorter, and there are no watchers which are resource-expensive. Also it handles removing items from the user's search at the same time.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM