Issue with passing the data in Vue / EventBus - vue.js

I have an issue that I do not understand regarding passing data in Vue.
In store I have the following data (six categories - wine, beer, whiskey, gin, vodka and rum):
state: {
shopItems: [
{
id: 1,
category: "wine",
price: 20,
image:
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD//Z",
items: [
{
id: 1,
name: "Ruby",
price: 17,
image:
"https://images.freshop.com/1564405684707189696/e52a7445e17de485c0ae890de8762d57_medium.png"
},
{
id: 2,
name: "Sauvignon Blanc",
price: 23,
image:
"https://ipcdn.freshop.com/resize?url=https://images.freshop.com/00898322593368/2e0ad0dbe0ef46eded5590acdf43cae5_large.png&width=256&type=webp&quality=40"
},
{
id: 3,
name: "Dark Horse",
price: 25,
image:
"https://ipcdn.freshop.com/resize?url=https://images.freshop.com/00085000024218/680b13803f3203f3117eb69082f95cc2_large.png&width=256&type=webp&quality=40"
},
{
id: 4,
name: "Andree",
price: 35,
image:
"https://ipcdn.freshop.com/resize?url=https://images.freshop.com/00085000008287/17d49b2b92223defb638ca7b535dbab3_large.png&width=256&type=webp&quality=40"
}
]
},
{
id: 2,
category: "beer",
price: 3,
image:
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxIQEhAQEg8TFhEXExYSGRcVFRYSEhYVGBUYGBUVFRYcAAEAAgIDAQAAAAAAAAAAAAAABgcEBQEDCAL/",
items: [
{
id: 1,
name: "Banana",
price: 5,
image:
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxAQDxIPEhIPFRAPEhcPEBYSEBgSDw8QFRIS0tLS0uLi0tLS8tLS8tLi0tLS0tLi0tLS8tLS0wLS0tLS0tLS0tLSstLf/AABEIAOEA4QMBEQACEQEDEQH/xAAcAAEAAgIDAQAAAAAAAAAAAAAABQYEBwECCAP/"
},
{
id: 2,
name: "Franziskaner Weissbier",
price: 6,
image:
"data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD/2wCEAAkGBxIQEhAQEg8TFhEXExYSGRcVFRYSEhYVGBUDEQH/xAAcAAEAAgIDAQAAAAAAAAAAAAAABgcEBQEDCAL/xABIEAACAgECAgcEBwQFCgcAAAAAAQIDEQQhBRIGBxMiMUFRYXGBwRQjMnKRobFCUpLCJDNigtE0Q1 "
},
{
id: 3,
name: "Birra Moretti",
price: 5,
image:
"data:image/jpeg; QQFEiExBgcTIkFRYXGBFCMycpGhsdEkM0JSYsE1Q1OCkhUWJTREVIOTotLh8PH/xAAaAQEAAwEBAQAAAAAAAAAAAAAAAgMEAQUG/8QANBEBAAICAAQDBQcEAgMAAAAAAAECAxEEEiExE0FRBSIyYXGBkaGxwdHwFEJS4SPxFTOC/9oADAMBAAIRAxEAPwDuMBAQEBAQEBAQEBAQNHau1adKoe59wE7q91mLN5BVBJ+ "
}
]
},
.
.
.
In my application I am passing the data related to the index of the chosen category from ToBeBought component to ShowDetails component – using EventBus.
showDetails(item) {
console.log("#item.category");
console.log(item.category);
const chosenCategoryIndex = this.shopItems.findIndex(
i => i.category === item.category
);
// const chosenCategoryItems = this.shopItems[chosenCategoryIndex]
// .items;
console.log("#chosenCategoryIndex");
console.log(chosenCategoryIndex);
EventBus.$emit("chosenCategory", chosenCategoryIndex);
this.$router.push("/details");
I pass the index of the chosen category - e.g. for wine index is 0.
I run chosenCategoryItems method on mounted
(I tried running it on created as well but it did not help)
to get the data in ShowDetails component. In console.log from this method I get an array with detailed data e.g. wines but after that method in mounted I have another console log to show the array (console.log(this.detailedItemsToBeBought);) - I get undefined from it.
It looks like the data was cleared in the meantime - I do not get what is going on here.
I tried to add watcher on detailedItemsToBeBought data but it is not being triggered.
data() {
return {
itemsToBeBought: [],
detailedItemsToBeBought: []
};
},
mounted() {
this.chosenCategoryItems();
console.log("#detailedItemsToBeBought mounted");
console.log(this.detailedItemsToBeBought);
console.log("#this.shopItems[0].items");
console.log(this.shopItems[0].items);
},
methods: {
chosenCategoryItems() {
EventBus.$on("chosenCategory", data => {
const chosenCategoryIndex = data;
console.log("#chosenCategoryIndex");
console.log(chosenCategoryIndex);
this.detailedItemsToBeBought = this.shopItems[
chosenCategoryIndex
].items;
console.log("#detailedItemsToBeBought event bus");
console.log(this.detailedItemsToBeBought);
});
return this.detailedItemsToBeBought;
}
When I try to display the data I do not see anything but when hardcode this.shopItems[0].items I get the data I need - e.g. for wine category the array with wines;
I know it is not an easy issue but is anyone able and willing to take the challenge to explain me whot might had gone wrong here. Why I get the data from this.shopItems[0].items but when I pass index to this.detailedItemsToBeBought = this.shopItems[chosenCategoryIndex].items; - it works fine in the method chosenCategoryItems but after that the data this.detailedItemsToBeBought are undefined on mounted?
I attach screenshot from console.
[![enter image description here][1]][1]
[1]: https://i.stack.imgur.com/30rk7.png
and the whole repository:
https://github.com/agnesliszka/alcohol_shop

It looks like your component needs to register for the listener BEFORE you emit the event.
You might want to simply store the chosen category in the store, instead of using an event.
If you really want to use an event (not recommended), you can delay the emit until after the component is ready, using nextTick or setTimer.
You will also want to register the listener in created or mounted.
this.$nextTick(()=>{
EventBus.$emit("chosenCategory", chosenCategoryIndex);
})
this.$router.push("/details");

Related

react native redux toolkit how can I pass data to array?

How can I pass data to array (redux toolkit) ?
I tried this but not working.
I have an array of shippers:
const shipper = [
{
type: 'NORMAL',
item: {
id: 1,
name: 'SHIPPER1',
}
},
{
type: 'NORMAL',
item: {
id: 2,
name: 'SHIPPER2',
}
},
{
type: 'NORMAL',
item: {
id: 3,
name: 'SHIPPER3',
}
},
{
type: 'NORMAL',
item: {
id: 4,
name: 'SHIPPER4',
}
},
{
type: 'NORMAL',
item: {
id: 5,
name: 'SHIPPER5',
}
},
];
I want to add each item to the reducer array. Like this without redux.
setShippers(prevState => {
return [...prevState, shipper];
});
But I want it in Redux Toolkit:
slice/shipper.js
import { createSlice } from "#reduxjs/toolkit";
const createProductShipper = createSlice({
name: "createProductShipper",
initialState: {
shippers: []
},
reducers: {
AddProductShipper(state, action) {
state.shippers = [...state.shippers, action.payload];
},
}
});
export const { AddProductShipper } = createProductShipper.actions;
export default createProductShipper.reducer;
...
dispatch(AddProductShippers({id, shipper});
...
..................................................................................................................................................................................................................
I’m a bit confused about whether the shipper variable is an array or a single shipper — and I suspect that you are too.
Your “without redux” example would be the correct way to add a single shipper to the array. If shipper is an array then you’ll want to spread both prevState and shipper:
setShippers(prevState => [...prevState, …shipper]);
The same goes for the redux reducer.
But the way that you are calling the dispatch seems strange:
dispatch(AddProductShippers({id, shipper}));
This will dispatch an action whose payload has properties id and shipper. Is that what you want? What is the id property: the product id or the shipper id?
Assuming that the product id is irrelevant (it appears nowhere in your slice) and that you want to add an array of shippers, your code might look something like this:
dispatch(AddProductShippers(arrayOfShippers));
AddProductShipper(state, action) {
state.shippers = [...state.shippers, …action.payload];
}
Or
AddProductShipper(state, action) {
state.shippers.push(…action.payload);
}

How to Reuse array in Vue app , declare it once & use in more than one file?

i have an array of products
const products = [
{ id: 1, productname: "64GB Phone", qty: 1, price: 33070, image:
require('../assets/phone.png') },
i have added this into 3 files
is their any way i can declare this in one file & call it in 3 files without writing the whole array ?
One valid pattern is to use mixins:
import { reusableMixin as products } from "#/mixins/reusableMixin"
const component = {
mixins: [
products
],
data(){
return {...}
},
...
}
___________________________
export const reusableMixin = {
data(){
return {
products: [...]
}
}
// or when piping
computed:{
products_piped: {
get(){
return getFromAnywhereSync()
},
set(val){
setSomeWhere(val)
}
}
}
}
If you want to make changes on this array and all pages get that change then import is not the correct way because if you change it in one component the other component will not take that change. if you want something like this you have to add it in store (vuex) tell us exacly what do you need it for to help you ^^
You can set a prototype in your main.js file as follows:
Vue.prototype.$products = {
id: 1, productname: "64GB Phone", qty: 1, price: 33070, image:
require('../assets/phone.png')
};
Then, use this.$products within your Vue components.
(You have an erroneous open square bracket here: const products = [ in your example)

Using nested include on an array

I am trying to verify that an array has 2 elements with the following values:
expect([{
createdAt: 1545588925941,
updatedAt: 1545588925941,
id: '5c1fd0bdd38b1b2bb0875dd9',
readAt: null,
type: 'ResidentCreatedTask',
dataVersion: 0,
data: '{}',
user: '5c1fd0bdd38b1b2bb0875dd6',
home: '5c1fd0bdd38b1b2bb0875dd8'
},
{
createdAt: 1545588925941,
updatedAt: 1545588925941,
id: '5c1fd0bdd38b1b2bb0875dd9',
readAt: null,
type: 'ResidentCreatedTask',
dataVersion: 0,
data: '{}',
user: '5c1fd0bdd38b1b2bb0875dd6',
home: '5c1fd0bdd38b1b2bb0875dd8'
}
]).to.be.an('array').that.has.lengthOf(2).and.to.deep.nested.include({
0: {
type: 'ResidentCreatedTask'
},
1: {
type: 'ResidentCreatedTask'
},
});
But it's not working. I also tried changing the keys to strings with brackets like '[0]' and '[1]'.
I also tried removing the keys and making the val of includes an array like this:
.include([{ type: 'ResidentCreatedTask' }, { type: 'ResidentCreatedTask' }]);
But this also didn't work.
I don't like this solution, but you can wrap it an object.
So our payload is const payload = [{ id: 0 },{ id: 1 }]. Doing the following will not work, this is what I did in original post:
expect(payload).to.nested.include({ '[0].id': 0, '[1].id': 1 });
Work around is:
const wrappedPayload = { a: payload };
expect(wrappedPayload).to.nested.include({ 'a[0].id': 0, 'a[1].id': 1 });
This works, but I don't like having to wrap it. Very much still open to solutions. Is this a bug I should report to chai team?

How to store multiple api's data with VueX and add properties to the response

Suppose i want to store data from multile Api requests - when the App is instantiated,
and i also want to add properties to each response
Here is the url of the api 'http://api.open-notify.org/iss-pass.json?lat=LAT&lon=LON'
Updated
I want to instantiated the app with all the data from a couple of get requests - so i'm looping all the requests - that part is works fine , but i also want to be able to add to response.data.response object properties from the cities array, so the finale result will be :
cities: [{
id: 0,
cityName: 'Select a city',
stuff from response.data...
},......
Here is the main part of the Api call
const store = new Vuex.Store({
state: {
satelliteData: [],
dataObj:[],
loading: true,
cities: [{
id: 0,
cityName: 'Select a city',
cityLocation: null
},
{
id: 1,
cityName: 'Tel Aviv',
cityLat: '32.0853',
cityLon: '34.7818'
},
{
id: 2,
cityName: 'London',
cityLat: '51.5074',
cityLon: '-0.1278'
},
{
id: 3,
cityName: 'New York',
cityLat: '40.7128',
cityLon: '-74.0060'
},
],
},
actions: {
loadData({commit}) {
for(var i=0; i<this.state.cities.length; i++){
var currData = this.state.cities[i];
if(!!this.state.cities[i].hasOwnProperty('cityLat'))
axios.get(URL, {
params: {
lat: this.state.cities[i].cityLat,
lon: this.state.cities[i].cityLon,
},
}).then((response) => {
Here is where i want to be able to access the Cities array
/* var cities = this.$store.state.cities;
console.log(cities) */
commit('updateSatelliteData', response.data.response)
commit('changeLoadingState', false)
})
}
}
},
Fiddle
Since i'm new to Vue - i'm sure that there are a couple of mistakes here. Thanks

Find object by match property in nested array

I'm not seeing a way to find objects when my condition would involve a nested array.
var modules = [{
name: 'Module1',
submodules: [{
name: 'Submodule1',
id: 1
}, {
name: 'Submodule2',
id: 2
}
]
}, {
name: 'Module2',
submodules: [{
name: 'Submodule1',
id: 3
}, {
name: 'Submodule2',
id: 4
}
]
}
];
This won't work because submodules is an array, not an object. Is there any shorthand that would make this work? I'm trying to avoid iterating the array manually.
_.where(modules, {submodules:{id:3}});
Lodash allows you to filter in nested data (including arrays) like this:
_.filter(modules, { submodules: [ { id: 2 } ]});
Here's what I came up with:
_.find(modules, _.flow(
_.property('submodules'),
_.partialRight(_.some, { id: 2 })
));
// → { name: 'Module1', ... }
Using flow(), you can construct a callback function that does what you need. When call, the data flows through each function. The first thing you want is the submodules property, and you can get that using the property() function.
The the submodules array is then fed into some(), which returns true if it contains the submodule you're after, in this case, ID 2.
Replace find() with filter() if you're looking for multiple modules, and not just the first one found.
I think your best chance is using a function, for obtaining the module.
_.select(modules, function (module) {
return _.any(module.submodules, function (submodule) {
return _.where(submodule, {id:3});
});
});
try this for getting the submodule
.where(.pluck(modules, "submodules"), {submodules:{id:3}});
I looked into this and I think the best option is to use Deepdash. It's a collection of methods to do deeply filter, find etc.
Sure it would be possible with lodash alone but with Deepdash it's easier.
I tried to convert the previous answer to the latest Lodash version but that was not working. Every method was deprecated in v4 of Lodash. Possible replacements: select = map or filter, any = some, where = filter)
findDeep returns an object with some information to the found item (just some values, see the docs for more details):
value is the object found
key that's the index in the nested array
parent the parent of the value
So the code for the findDeep looks like:
const modules = [{
name: 'Module1',
submodules: [{
name: 'Submodule1',
id: 1
}, {
name: 'Submodule2',
id: 2
}]
}, {
name: 'Module2',
submodules: [{
name: 'Submodule1',
id: 3
}, {
name: 'Submodule2',
id: 4
}]
}];
const getModule = (modules, id) =>
_.findDeep(modules, module => module.id === id, {
childrenPath: "submodules"
});
const resultEl = document.getElementById("result");
const foundModule = getModule(modules, 3).value;
resultEl.innerText = JSON.stringify(foundModule, null, 2);
<script src="https://cdn.jsdelivr.net/npm/deepdash/browser/deepdash.min.js"></script>
<script src="https://cdn.jsdelivr.net/npm/lodash/lodash.min.js"></script>
<script>
deepdash(_);
</script>
<h2>Example to get module with id = 3</h2>
<pre id="result"></pre>