I have a list of Items:
const items = [{id: 1, linked_id: 5}, {id: 2, linked_id: 1}, {id: 3, linked_id: 5}, {id: 4, linked_id: 1}, {id: 5, linked_id: 1}];
Im rendering it like this:
<div style="max-height: 150px; overflow: auto;">
<ul>
{items.map((item) => <Item key={item.id} {...item}/>)}
</ul>
</div>
And the Item component looks like this:
const Item = ({id, linked_id}) => {
const handleClick = () => {
// ???
}
return (<li>
<button onClick={handleClick}>[Scroll to: {linked_id}]</button>
</li>)
}
When i click button inside Item, i need parent div (the one with overflow: auto) to scroll to linked Item. How to i solve it cleanly? Do i need to forward parent div reference to every Item and then make checks inside every Item? Seems excessive
Related
i have a scenario where I am triggering an event on button click after selecting elements from the grid when the button is clicked I need to remove that element from the current modal/grid
CheckedNames:["a","b","c"],
CheckedNamesId:[1,2,3],
DeletefromArray(){
this.CheckedNames.forEach(element => {
this.deleteItem(this.CheckedNamesId,this.CheckedNamesId.length);
});
},
deleteItem(index,length) {
this.List.splice(index, length)
},
check: function(e,row) {
this.CheckedNamesId.push(row.id)
console.log(this.CheckedNamesId)
},
Now if I select "a","b","c" by the check box, I need to remove it from the array,
If I understood you correctly try something like following snippet:
new Vue({
el: '#demo',
data() {
return {
names: [{id: 1, name: 'a'},{id: 2, name: 'b'}, {id: 3, name: 'c'}, {id: 4, name: 'd'}, {id: 5, name: 'e'}, {id: 6, name: 'f'}, {id: 7, name: 'g'}],
checkedNames: []
}
},
methods: {
check(item) {
if (!this.checkedNames.length || !this.checkedNames.find(f => item.id === f.id)) {
this.checkedNames.push(item)
} else {
this.checkedNames = this.checkedNames.filter(f => item.id !== f.id)
}
},
del() {
this.names = this.names.filter(a => !this.checkedNames.includes(a))
this.checkedNames = []
}
}
})
Vue.config.productionTip = false
Vue.config.devtools = false
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.5.17/vue.js"></script>
<div id="demo">
<ul>
<li v-for="item in names" :key="item.id">
{{ item.name }}
<input type="checkbox" #click="check(item)" />
</li>
</ul>
<button #click="del">Delete</button>
</div>
You can try like the code below. When looping in List array check if id of the element is present in checkedNameID array by using indexof. If present add that element's index in a array defined outside loop. Then you can slice it away using another loop from array. When you slice use 1 as second parameter it will remove 1 element at a a time in loop.
const arr = []
deleteFromArray(){
this.List.forEach((element,index) => {
if(this.checkedNameID.indexOf(element.id) !== -1){
this.arr.push(index);
}
});
arr.forEach(item => {
this.List.splice(index,1);
}
},
I am using react-native-select-dropdown and set data array statically but don't know how to set data array dynamically from apis with id
Code :
const countries = ["Egypt", "Canada", "Australia", "Ireland"]
<SelectDropdown
data={countries}
// defaultValueByIndex={1}
// defaultValue={'Egypt'}
onSelect={(selectedItem, index) => {
console.log(selectedItem, index);
}}
defaultButtonText={"Select"}
buttonTextAfterSelection={(selectedItem, index) => {
return selectedItem;
}}
rowTextForSelection={(item, index) => {
return item;
}}
/>
how to set countries array list dynamically and i need both title and id of selected item, the fetching data from api are:
const countries = [
{namd: 'Egypt', id: 1},
{namd: 'Canada', id: 2},
{namd: 'Australia', id: 3},
{namd: 'Ireland', id: 4},
];
Here is an example from your code as per your requirement. In below code dropdown menu will show the country names and when you select any one of them, then it will print the selected country and id. You can use the useState hook to manage API calls. I have shown you the example how you can manage the response for dropdown.
You can check this snack example I just made - https://snack.expo.dev/hRpKm2bdg
const countries = [
{namd: 'Egypt', id: 1},
{namd: 'Canada', id: 2},
{namd: 'Australia', id: 3},
{namd: 'Ireland', id: 4},
];
export default function App() {
return (
<View>
<SelectDropdown
data={countries}
onSelect={(selectedItem, index) => {
console.log('selected Country name ->>>>',selectedItem.namd)
console.log('selected Country Id ->>>>',selectedItem.id)
}}
buttonTextAfterSelection={(selectedItem, index) => {
// text represented after item is selected
// if data array is an array of objects then return selectedItem.property to render after item is selected
return selectedItem.namd
}}
rowTextForSelection={(item, index) => {
// text represented for each item in dropdown
// if data array is an array of objects then return item.property to represent item in dropdown
return item.namd
}}
/>
</View>
);
}
I'm developing a Vue app and I have a list of movies like this:
movies [
{name: 'spider-man', id: 3},
{name: 'thor'},
{name: 'x-men', id: 7}
]
and this is my template
<ul>
<li v-for="movie in movies" :key="movie.name">{{movie.name}}</li>
</ul>
I only wanna show the movies who has an ID, in this case, thor shouldn't be shown. I've tried with v-if but I got this error: "The 'movies' variable inside 'v-for' directive should be replaced with a computed property that returns filtered array instead. You should not mix 'v-for' with 'v-if'".
Thanks, hope you can help me!
Computed properties to the rescue:
data: () => ({
movies: [
{name: 'spider-man', id: 3},
{name: 'thor'},
{name: 'x-men', id: 7}
]
})
...
computed: {
moviesWithId() {
return this.movies.filter(movie => movie.id)
}
}
...
In your template
<ul>
<li v-for="movie in moviesWithId" :key="movie.name">{{movie.name}}</li>
</ul>
Or you may add condition to render to your li tags like v-show="movie.id"
Or filter your dataset like :
<li v-for="movie in movies.filter(movie => movie.id)" :key="movie.name">{{movie.name}}</li>
There are several questions with answers on StackOverflow which shows how to find Cartesian product for various simple arrays. And a wonderful article on RosettaCode. But I can't find any solution for my problem.
I have an array of object with items, let's call it items:
let items = [{
id: 1
quantity: 2
field: "other_field"
},
{
id: 2
quantity: 3
field: "other_field"
}]
Every item in this array have a pricing/crafting method and we could receive it by request.
let pricing = getPricing(id) //item id
/*
Which will return to us:
*/
pricing = [
{pricing_id: 1, reagent_items: [/*array of objects, fields exactly items*/]},
{pricing_id: 2, reagent_items: [/*array of objects, fields exactly items*/]}
]
CARTESIAN PRODUCT PROBLEM:
As you may already understand, according to the answer's title, I want to receive all possible combinations of items AND reagent_items from pricing methods.
For example, if we have two items and all every item (of this 2) have just one pricing method, there will be 4 different combinations:
2 default items from items
first default item from items (item[0]) and all all reagent_items from getPricing for item[1]
second default item from items (item[1]) and all all reagent_items from getPricing for item[0]
both reagent_items from getPricing for both default items
I literally can't push reagent items to items (or remove item from items) array, because items can be the same (include each other) Instead of it, I am using my own Array.prototype.method for adding/removal items from items array. It does just the same as push/slice but in more elegant way, manipulating with id and quantity fields.
The actual problem lies in the field of arrays.length and for ... loop.
When we evaluate default Cartesian product we know before the array.length and it's elements.
But in my case I should getPricing every items, then receive array of methods..
Schema:
It's like:
Default: I_1 I_2 ... N
/ \ / \ / \
Get Pricing: [I_A, I_B][I_B, I_C] [IN_J, IN_K],
[IN_Y, IN_X, IN_Z],
So it's not about finding: Cartesian([I_A, I_B],[I_B, I_C]) but something like:
I_1 + I_2
I_1 + (I_B, I_C)
(I_A, I_B) + I_2
(I_A, I_B) + (I_B, I_C)
...
So default item includes each others and their reagent_items and it's simple to find all combinations of two items, but when it's become 3+..
My current pseudo code for now:
/* inside async*/
...
let ArrayOfPricing = [] //length 2, where each Array represent Array of `pricing` for each item
Promise.all(items.map(async item => {
const itemPricing = await getPricing(item.id);
ArrayOfPricing.push(itemPricing );
})
/**And what's next? **/
for (let item of items) {
}
So I can't understand what should I do next, at this stage.
Should I loop/iterate every item? But if so, even if I iterate every item one-by-one and change/remove it and add it's reagent_items (for every pricing) I still don't change the next item/element in array of items and it's length more then just 2, then I won't receive all the combinations, it will be like:
for items
↓
item[1] → for pricing
→ for reagent_items
↓
replace item[1] for all reagent_item
item[2] /** they are still there, but I need iterate over it's pricing , too **/
item[3]
or I could calculate all possible combinations by looking for items length and all pricing length and then form and empty new array with fixed length and push to all the combinations. But if I iterate over it for push with for loop... I should combine items and it will be for loop, inside for loop, inside for .. loop..
So to be honest I am out of ideas. I don't ask to write full working code instead of me, but to point me the way out of this loop. How to get every combination for every item and "baby-items" inside of it? How many cycles should I use then? I'll be grateful for any useful idea/pseudocode/post link which will help me to deal with this case. I'm also here and will check all the comments and answers below.
UPD a simple version of «from what I get, to what I want»
from this:
[
{
field: "original, can be cloned for every combination",
items:
[
{id: 1, quantity: 2},
{id: 2, quantity: 3}
]
}
]
to:
[
{
field: "original",
items:
[
{id: 1, quantity: 2},
{id: 2, quantity: 3}
]
},
{
field: "combination1",
items:
[
{id: 11, quantity: 1}, //from getPricing(item[0])
{id: 12, quantity: 1}, //from getPricing(item[0])
{id: 2, quantity: 3}
]
},
{
field: "combination2",
items:
[
{id: 1, quantity: 2},
{id: 22, quantity: 3} //from getPricing(item[1])
{id: 23, quantity: 3} //from getPricing(item[1])
]
},
{
field: "combination3",
items:
[
{id: 11, quantity: 1}, //from getPricing(item[0])
{id: 12, quantity: 1}, //from getPricing(item[0])
{id: 22, quantity: 3} //from getPricing(item[1])
{id: 23, quantity: 3} //from getPricing(item[
]
}
//can be any length according to getPricing of every item, and I modify original array, but we could create a new one.
]
As I promised, I have found a solution of my problem and I'd like to share it with StackOverflow Community.
Pseudo-code:
let array = [
{
field: "original, can be cloned for every combination",
items:
[
{id: 1, quantity: 2},
{id: 2, quantity: 3}
]
}
]
for (let element of array) {
let MethodsCombinations = [];
for await (let forCombinations of element.items.map((item, i) => {
return getMethod(item.id) //get Method for each item)
})) {
MethodsCombinations.push(forCombinations)
}
/* Cartesian product */
let vanilla_CartesianProduct = MethodsCombinations.reduce((a, b) => a.reduce((r, v) => r.concat(b.map(w => [].concat(v, w))), []));
/* Return array of arrays, with objects inside like default array */
/**
* Other logic with two for loops and merging all the combinations and quantities
* with (my own) modified Array.prototype.addItemToArray
*/
}
I am very grateful to this Nina Scholz's answer and her awesome StackOverflow profile with all answers about combinations/permutations and for providing a support.
I really don't know how to explain this problem, but I have the fiddles to help:
Only line 25 gets changed
CORRECT: http://jsfiddle.net/0maphg47/5/
var ListAnimate = React.createClass({
getInitialState: function() {
return {
list: [
{id: 1, caption: "Hello"},
{id: 2, caption: "There"},
{id: 3, caption: "Whatsup"},
{id: 4, caption: "Sanket"},
{id: 5, caption: "Sahu"}
]
};
},
shuffle: function() {
this.setState({ list: this.state.list.shuffle() });
},
render: function() {
// create a sorted version of the list
var sortedCopy = this.state.list.slice().sort(function(a, b) {
return a.id - b.id;
});
return <div>
<button onClick={this.shuffle}>Shuffle</button>
<ul>
{sortedCopy.map(function(el, i) {
// find the position of the element in the shuffled list
var pos = this.state.list.indexOf(el);
return <li key={el.id} style={ {top: (pos*60)+'px'} }>
{el.caption} {el.id}
</li>;
}, this)}
</ul>
</div>;
}
});
React.render(<ListAnimate />, document.body);
WRONG: http://jsfiddle.net/0maphg47/6/
var ListAnimate = React.createClass({
getInitialState: function() {
return {
list: [
{id: 1, caption: "Hello"},
{id: 2, caption: "There"},
{id: 3, caption: "Whatsup"},
{id: 4, caption: "Sanket"},
{id: 5, caption: "Sahu"}
]
};
},
shuffle: function() {
this.setState({ list: this.state.list.shuffle() });
},
render: function() {
// create a sorted version of the list
var sortedCopy = this.state.list.slice().sort(function(a, b) {
return a.id - b.id;
});
return <div>
<button onClick={this.shuffle}>Shuffle</button>
<ul>
{this.state.list.map(function(el, i) {
// find the position of the element in the shuffled list
var pos = this.state.list.indexOf(el);
return <li key={el.id} style={ {top: (pos*60)+'px'} }>
{el.caption} {el.id}
</li>;
}, this)}
</ul>
</div>;
}
});
React.render(<ListAnimate />, document.body);
Why do we have to render the li objects in the same order every time if the key can determine uniqueness? I don't get why the order of the li elements matter, but I'm probably missing something obvious
Take a look in the Elements view of your browser's debugger to see what is happening to the DOM when you click on the Shuffle button.
In the first (correct) case, the only thing that changes in the DOM is the style attribute of each list item. The order and contents of the items don't change, only the appearance of the order changes. The element of key X was remains in the same position before and after the shuffle, so new DOM elements do not need to be created.
In the second (wrong) case, the actual order of the elements is shuffled. While key 1 may be in first position before the shuffle, it may in the fourth position after the shuffle. The attributes of the items are not being updated in place; rather, React may be creating new items where an item has changed positions. Hence, this can have an unpredictable effect on your transitions.