Method to check if item is saved within the Nuxt Store - vue.js

I currently have a Store that has the "Saved" items from a feed for a user. I'm trying to figure out the best/efficient way to check if the item is already saved within the store.
I can't think of any other way than grabbing the entire store's contents in each feed item and checking whether the id exists? Surely there's a better way?
FeedItem.vue
methods: {
savePost(Post) {
this.$store.commit('savedPosts/addItem', Post)
},
deletePost(Post) {
this.$store.commit('savedPosts/removeItem', Post)
}
}
Store
export const state = () => ({
items: [
],
})
export const mutations = {
updateItemsOnLoad(state, array) {
var oldItems = state.items
var newItems = array.flat()
var joinedItems = newItems.concat(oldItems);
state.items = joinedItems.flat()
},
addItem(state, item) {
state.items.push(item)
this.$warehouse.set('savedPosts', state.items)
},
removeItem(state, item) {
var index = state.items.findIndex(c => c.id == item.id);
state.items.splice(index, 1);
this.$warehouse.set('savedPosts', state.items)
},
}
So my main question: Is there a more efficient way to check whether a post exists within the items array without querying it on every feed item?

Related

How to search inside an array property of an index

I have to retrieve a list of apps that have certain string inside of an array property:
const users = algoliaClient.initIndex('apps')
return users.search('myId123', { hitsPerPage: 50 });
The apps objects are just like this:
{categories: ['an', 'interesting', 'category']}
How can I search the index for items with a categories property that contains any item in an array of strings?
const search = ["cat1", "cat2", "cat3"];
const apps = [
{
name: "app1",
categories: ["cat1", "cat5"],
},
{
name: "app2",
categories: ["cat2", "cat4"],
},
];
is that what you mean ? if so :
var myIndexes = [];
apps.forEach((app, index) => {
search.every((search) => {
if (app.categories.includes(search)) {
myIndexes.push(index);
return false; // return false here is for stoping the EVERY loop
} else {
return true; // keep running the EVERY loop
}
});
});

Vuex passing different arrays

Making a filter:
Mutations
export default {
state: {
filteredBrands: []
},
mutations: {
showFilteredList(state, payload) {
state.filteredBrands.push(payload);
}
}
};
Methods
loadProducts(item) {
axios.get('/api', {
params: {
per_page: 20,
filter_machinery_brands: [ item ]
}
})
.then((response) => {
this.$store.commit(
'showFilteredList',
response.data
);
});
},
item this is an input with a checkbox, when clicked, a request is made to the server for this category
For some reason, the push does not work, why?
And I would like there to be a check, if the array is the same, then delete, otherwise add. Is it possible?
If you can se an array comes in as payload. Then you are trying to push an array into an array. Which cant be done in either js or ts.
You can try set the value:
state.filteredBrands = payload;
otherwise you would have to do something like this:
state.filteredBrands.push(payload[0]);
If you wanna control for existing items in array, and assuming your are not always setting value, but pushing new values into your array. You can do something like this:
if (state.filteredBrands.indexOf(payload[0]) === -1) {
// Not in array
state.filteredBrands.push(payload[0])
} else {
// is allready in array
state.filteredBrands.forEach((item, index) => {
if (item === payload[0]) {
state.filteredBrands.splice(index, 1)
}
})
}
EDIT:
My assumption was right.
Your payload is an array
Your state is an array
-------> You are trying to push payload(array) into state(array) - which cant be done i js - This solution would after my suggestion be more clean:
payload.forEach((value, index) => { // Looping payload
if (state.filteredBrands.indexOf(value) === -1) {
state.filteredBrands.push(value) // push if value not allready in array
} else {
state.filteredBrands.splice(index, 1) // if value is in array -> remove
}
})
Yes, you can push an array into an array.
I guess the problem here is your vuex config.
Vuex state is a function, so it needs to be:
state () {
return {
filteredBrands: []
}
}
And if you are using Nuxt:
export const state = () => ({
filteredBrands: []
})

How to refresh view when vuex store changes?

I get the data from the store like so
computed: {
notes() {
var data = this.$store.getters.getNotes;
var key = this.$store.getters.getTitleFilter;
if (key === "all") return data;
return data.filter((note) => {
var filteredNote = note.category.some(({ name }) => name === key);
if (filteredNote) return filteredNote;
});
},
},
When the note array changes (an item is removed, getNotes should reflect that. In other instances (where the data is returned without filtering) this used to do the trick:
watch: {
notes(newval) {
return newval;
},
},
I there a way to get the filtered array to update?

How to share the composition across components in api-composition style?

In my application I have two separate components:
products component (show the products in the ui)
filter-products component (show the criteria in ui)
total-filter-products component (show the total criteria items was applied in ui, for example my current search is age,name so on)
They are separate and not communicate with input (:) or output (#).
I also have a ts file, with function useProducts as "api-composition style".
export const useProducts = () => {
const criteria = ref({ category: null, age: null, color: null });
const items = computed(() => { return store.get('products').filter(p => filterByCritiria(p)) });
const load = () => {
const params = parseSome(criteria.value);
axios.post('/api/...', { params }).then(r => { store.set('products', r.data)});
}
return { criteria, items, load }
}
In the products component, I just get the products from useProducts and bind to the template:
setup() {
const { products } = useProducts();
return { products }
}
In the filter-products, I get the criteria from useProducts and bind to the template. every time some value change in criteria ref (using v-model), I run the load function.
setup() {
const { criteria, load } = useProducts();
watch(() => criteria.value, (v) => load() });
return { criteria }
}
In total-filter-products component I do some logic to display the criteria:
setup() {
const { criteria } = useProducts();
return { criteria: parse(criteria) }
}
The problem with this is every time I call to useProducts I execute the function and get new variables.
I get three times the criteria. so if I change the criteria in filter-products, the total-filter-products and products components will never know about it.
How to share the composition across components in api-composition style?

Vue.js Vuex - Delete in Database not reflected in view

I have a number of companies in the Vuex Store. Each company object has several objects within it ... to simplify for my question, imagine
company{ id: 1, approval_notes: [{id: 1}, {id: 2}, {id: 3}], fins:
{total_rev: 10000} }
I want to remove the approval_note with id of 2 from the company with the id of 1.
In the view, I have
deleteNote(obj) {
if(confirm('Are you sure you want to delete this note?')) {
let path = '/api/approval_notes/' + obj.id;
axios.delete(path)
.then(function(rsp) {
this.$store.dispatch('delete_approval_note', obj);
}.bind(this))
.catch(function (err) {
console.log('AXIOS ERR', err);
}.bind(this));
}
}
The action is
export const delete_approval_note = ({commit}, payload) => {
commit('DELETE_APPROVAL_NOTE', payload);
};
And the mutation is
export const DELETE_APPROVAL_NOTE = (state, payload) => {
_.each(state.companies, function(co) {
if(co.id = payload.company_id) {
let notes = co.approval_notes;
notes.splice(notes.indexOf(payload), 1);
}
});
};
The note is deleted from the database but the view does not update without a page refresh.
This type of thing I will be doing a bunch so it's important to me to understand this process since I obviously don't get it right now.
Any help is appreciated.
Instead of IndexOf, using
notes.findIndex(obj => obj.id == payload.id)
It can get tricky when using IndexOf with complex object, I mostly rely on indexOf if dealing with simple values (integers, strings, booleans)