React native: How to make horizontal scroll but data is divided to 4 rows - react-native

I need to scroll my items horizontally but my data is divided to 4 rows every row contain 4 items. and I can scroll horizontally so the next 16 item come to the screen.
when using numColumns={4} it works if
horizontal={false}
but with
horizontal={true}
I can't specify numColumns attr.
Should I use SectionList instead of FlatList ?
and how it could be implemented ?
let items = [
{ id: 1, title: '1', price: '20' },
{ id: 2, title: '2', price: '16' },
{ id: 3, title: '3', price: '92' },
{ id: 4, title: '4', price: '93' },
{ id: 5, title: '5', price: '20' },
{ id: 6, title: '6', price: '16' },
{ id: 7, title: '7', price: '92' },
{ id: 8, title: '8', price: '93' },
{ id: 9, title: 'Grilled Steak', price: '20' },
{ id: 10, title: 'Pappas', price: '16' },
{ id: 11, title: 'Ciccione', price: '92' },
{ id: 12, title: 'Gyros Melt', price: '93' },
{ id: 13, title: 'Grilled Steak', price: '20' },
{ id: 14, title: 'Pappas', price: '16' },
{ id: 15, title: 'Ciccione', price: '92' },
{ id: 16, title: 'Gyros Melt', price: '93' },
];
<FlatList
keyExtractor={item => item.id}
data={items}
horizontal
numColumns={4}
renderItem={({ item }) => <Text>{item.title}</Text>}
/>

I have the same issue with same scenario. making group data is quite a bad practice in case you have long array. so I play with styles of flatlist and I was successful. following is my code if you can take advantage out of it:
<ScrollView showsHorizontalScrollIndicator={false} horizontal={true} style={styles.flatListContainer}>
<FlatList
showsHorizontalScrollIndicator={false}
data={item.items}
numColumns={4}
renderItem={_showData}
columnWrapperStyle={styles.flatListColumnWraper}
keyExtractor={(item) => item.key}
style={styles.flatListDataContainer}
scrollEnabled={false}
contentContainerStyle={
styles.flatListContentContainerStyle
}
/>
</ScrollView>
flatListContainer: {
marginTop: height(2),
height:height(60),
paddingVertical:height(2)
},
flatListDataContainer: {
alignSelf: 'center',
},
flatListContentContainerStyle: {
alignSelf: 'center',
flexDirection: 'row',
justifyContent: 'space-evenly',
},
flatListColumnWraper:{
flexDirection: 'column',
},

Unfortunately FlatList doesn't support a number of columns when it is horizontal.
https://facebook.github.io/react-native/docs/flatlist#numcolumns
Multiple columns can only be rendered with horizontal={false} and will
zig-zag like a flexWrap layout. Items should all be the same height -
masonry layouts are not supported.
However, you could group your data so that for every cell in a horizontal FlatList 4 items are rendered.
let items = [
[ { id: 1, title: '1', price: '20' },
{ id: 2, title: '2', price: '16' },
{ id: 3, title: '3', price: '92' },
{ id: 4, title: '4', price: '93' } ],
[ { id: 5, title: '5', price: '20' },
{ id: 6, title: '6', price: '16' },
{ id: 7, title: '7', price: '92' },
{ id: 8, title: '8', price: '93' } ],
[ { id: 9, title: 'Grilled Steak', price: '20' },
{ id: 10, title: 'Pappas', price: '16' },
{ id: 11, title: 'Ciccione', price: '92' },
{ id: 12, title: 'Gyros Melt', price: '93' } ],
[ { id: 13, title: 'Grilled Steak', price: '20' },
{ id: 14, title: 'Pappas', price: '16' },
{ id: 15, title: 'Ciccione', price: '92' },
{ id: 16, title: 'Gyros Melt', price: '93' } ]
];
Then update your renderItem so that it handles the increased input, something like this.
renderItem = ({item}) => {
return item.map(i => <Text>{i.title}</Text>)
}

Related

Series in ECharts.js

How can I make the label display the value of not only one series, but the entire stack in Echarts.js? How can I make the border line go between each column, not just between columns of different x-axis values? I read the documentation, but did not find a solution to these issues there.
Chart
I wrote such settings in the configuration, but this, of course, is not what you need.
series: [
{
name: 'Matcha',
type: 'bar',
stack: 'drinks',
data: data.filter(item => item.name === 'Matcha').map(item => item.value),
},
{
name: 'Green tea',
type: 'bar',
stack: 'drinks',
data: data.filter(item => item.name === 'Green tea').map(item => item.value),
label: {
show: true,
position: 'top',
fontSize: 14,
fontWeight: 700,
},
},
{
name: 'Apple',
type: 'bar',
stack: 'fruits',
data: data.filter(item => item.name === 'Apple').map(item => item.value),
},
{
name: 'Orange',
type: 'bar',
stack: 'fruits',
data: data.filter(item => item.name === 'Orange').map(item => item.value),
label: {
show: true,
position: 'top',
fontSize: 14,
fontWeight: 700,
},
}
],

Change the images based on the item's categories react native

I'm making a budget tracker app. And I'm implementing the functions display and add transactions for the app. However, I'm struggling to find a way to dynamically set the image URL (the icon) based on the transaction category type.
The app is written in React Native.
For example, I have a list of transactions as below:
[
{
id: 1,
type: 'Expense',
category: 'Food',
description: 'Burger',
amount: 100,
date: '2020-10-10',
createdAt: '2021-01-01',
},
{
id: 2,
type: 'Expense',
category: 'Entertainment',
description: 'Movie',
amount: 200,
date: '2020-10-10',
createdAt: '2021-10-02',
},
{
id: 3,
type: 'Income',
category: 'Salary',
description: 'Salary',
amount: 1000,
date: '2020-10-10',
createdAt: '2021-10-03',
},
{
id: 4,
type: 'Expense',
category: 'Food',
description: 'Burger',
amount: 100,
date: '2020-10-10',
createdAt: '2021-01-01',
},
]
Then I want to display it in a list, and each list item contains the icon representing the category, like this image:
You can just import images and add them as a key like this :
import burgerImage from '../images/burger.jpg';
import movieImage from '../images/movie.jpg';
[
{
id: 1,
type: 'Expense',
category: 'Food',
description: 'Burger',
amount: 100,
date: '2020-10-10',
createdAt: '2021-01-01',
icon: burgerImage,
},
{
id: 2,
type: 'Expense',
category: 'Entertainment',
description: 'Movie',
amount: 200,
date: '2020-10-10',
createdAt: '2021-10-02',
icon: movieImage
},
]
Pass the icon key as a source to Image component like this :
data.map((datum)=> <Image source={datum.icon} />);
I think you should use category field to render icon be like:
const renderIcon = (icon) => {
switch (icon) {
case "Food":
return <Icon icon="food" />
case "Movie":
return <Icon icon="movie" />
// Diff case
default:
return <Icon icon="iconDefault" />
}
And in renderItem of FlatList:
const renderItem = ({ item, index }) => {
return (
// render wrapper
{renderIcon(item.category)}
// render name, time, price of product
)
}

Multiple filters / Filter inside filter - React Native

how can i do something like that in React-Native:
data = [
{id:1,title:'Action',games:[
{id:1,title:'Game1'},
{id:2,title:'Game2'},
{id:3,title:'Game3'},
]},
{id:2,title:'Horror',games:[
{id:1,title:'Game1'},
{id:2,title:'Game2'},
{id:3,title:'Game3'},
]},
]
Every time the query string is updated, look for the game within the category.
Returns only the categories that contain a game with the searched characters.
Thank you! :D
I don't know if I understand your question correctly. This is my solution.
If you query for "Game5" you will get whole object that contains query
const data = [
{
id: 1,
title: "Action",
games: [
{ id: 1, title: "Game1" },
{ id: 2, title: "Game2" },
{ id: 3, title: "Game3" },
],
},
{
id: 2,
title: "Horror",
games: [
{ id: 1, title: "Game4" },
{ id: 2, title: "Game5" },
{ id: 3, title: "Game6" },
],
},
];
const query = "Game5";
const result = data.find((category) =>
category.games.find((g) => g.title === query)
);
console.log(result);
You can use 'filter' instead of 'find' and result will be an array.
This is example of filter version. I add one more category so you can see how it filter
const data = [
{
id: 1,
title: "Action",
games: [
{ id: 1, title: "Game1" },
{ id: 2, title: "Game2" },
{ id: 3, title: "Game3" },
],
},
{
id: 2,
title: "Horror",
games: [
{ id: 1, title: "Game1" },
{ id: 2, title: "Game2" },
{ id: 3, title: "Game3" },
],
},
{
id: 3,
title: "Comedy",
games: [
{ id: 1, title: "Game5" },
{ id: 2, title: "Game6" },
{ id: 3, title: "Game7" },
],
},
];
const query = "Game2";
const result = data.filter((category) =>
category.games.find((g) => g.title === query)
);
console.log(result);
And you might want to look at life cycle componentDidUpdate if you write class component, but if you write function component you might want to use useEffect
This is official react hook explaination
EDIT: from your comment you might want something like this
const data = [
{
id: 1,
title: "Action",
games: [
{ id: 1, title: "Game1" },
{ id: 2, title: "Game2" },
{ id: 3, title: "Game3" },
],
},
{
id: 2,
title: "Horror",
games: [
{ id: 1, title: "Game1" },
{ id: 2, title: "Game2" },
{ id: 3, title: "Game3" },
],
},
{
id: 3,
title: "Comedy",
games: [
{ id: 1, title: "Game5" },
{ id: 2, title: "Game6" },
{ id: 3, title: "Game7" },
],
},
];
const query = "Game5";
let result = null;
data.forEach((category) => {
const game = category.games.filter((g) => g.title === query);
if (game.length) result = { ...category, games: game };
});
console.log(result);

React Native state is not getting updated

I want to update state on button click
this.state = {
legend: {
enabled: true,
textSize: 14,
form: 'CIRCLE',
horizontalAlignment: "RIGHT",
verticalAlignment: "CENTER",
orientation: "VERTICAL",
wordWrapEnabled: true
},
data: {
dataSets: [{
values: [{value: 45, label: 'Sandwiches'},
{value: 21, label: 'Salads'},
{value: 15, label: 'Soup'},
{value: 9, label: 'Beverages'},
{value: 15, label: 'Desserts'}],
label: 'Pie dataset',
}],
},
highlights: [{x:2}],
description: {
text: 'This is Pie chart description',
textSize: 14,
textColor: processColor('darkgray'),
}
};
I want to update values array of state by using following code but
it didn't work
const myvalues=this.state.data.dataSets[0].values.map(l => Object.assign({}, l));
myvalues[1].label = 'NEw sandwich';
this.setState({values: myvalues}, () => {
console.log(this.state.data.dataSets[0].values[1].label + " it worksss");
});
I am stuck in this
Check this
const myvalues = [] /*your new array*/
this.setState((state) =>
{
data: {
...state.data,
values: myvalues
}
});

Resource squeezed in preview

I'm using this format:
https://fullcalendar.io/js/fullcalendar-scheduler-1.5.1/demos/vertical-resource-view.html
, but when I add more than 4 rooms, it gets squeezed. I wanted that by adding more rooms (I need 12) I would not get everything squeezed. How can I do this?
This my code:
<!DOCTYPE html>
<html>
<head>
<meta charset='utf-8' />
<link href='../lib/fullcalendar.min.css' rel='stylesheet' />
<link href='../lib/fullcalendar.print.min.css' rel='stylesheet' media='print' />
<link href='../scheduler.min.css' rel='stylesheet' />
<script src='../lib/moment.min.js'></script>
<script src='../lib/jquery.min.js'></script>
<script src='../lib/fullcalendar.min.js'></script>
<script src='../scheduler.min.js'></script>
<script>
$(function() { // document ready
$('#calendar').fullCalendar({
defaultView: 'agendaDay',
defaultDate: '2017-03-06',
editable: true,
selectable: true,
eventLimit: true, // allow "more" link when too many events
header: {
left: 'prev,next today',
center: 'title',
right: 'agendaDay,agendaTwoDay,agendaWeek,month'
},
views: {
agendaTwoDay: {
type: 'agenda',
duration: { days: 2 },
// views that are more than a day will NOT do this behavior by default
// so, we need to explicitly enable it
groupByResource: true
//// uncomment this line to group by day FIRST with resources underneath
//groupByDateAndResource: true
}
},
//// uncomment this line to hide the all-day slot
//allDaySlot: false,
resources: [
{ id: 'a', title: 'Consultório A' },
{ id: 'b', title: 'Consultório B', eventColor: 'green' },
{ id: 'c', title: 'Consultório C', eventColor: 'orange' },
{ id: 'd', title: 'Consultório D', eventColor: 'red' },
{ id: 'e', title: 'Consultório E', eventColor: 'blue' },
{ id: 'f', title: 'Consultório F', eventColor: 'yellow' },
{ id: 'g', title: 'Consultório G', eventColor: 'black' },
{ id: 'h', title: 'Consultório H', eventColor: 'white' },
{ id: 'i', title: 'Consultório I', eventColor: 'gray' },
{ id: 'j', title: 'Consultório J', eventColor: 'brown' },
{ id: 'k', title: 'Consultório K', eventColor: 'purple' },
{ id: 'l', title: 'Consultório L', eventColor: 'purple' },
{ id: 'm', title: 'Consultório M', eventColor: 'purple' }
],
events: [
{ id: '1', resourceId: 'a', start: '2017-03-06', end: '2017-03-08', title: 'event 1' },
{ id: '2', resourceId: 'a', start: '2017-03-07T09:00:00', end: '2017-03-07T14:00:00', title: 'event 2' },
{ id: '3', resourceId: 'b', start: '2017-03-07T12:00:00', end: '2017-03-08T06:00:00', title: 'event 3' },
{ id: '4', resourceId: 'c', start: '2017-03-07T07:30:00', end: '2017-03-07T09:30:00', title: 'event 4' },
{ id: '5', resourceId: 'd', start: '2017-03-07T10:00:00', end: '2017-03-07T15:00:00', title: 'event 5' }
],
select: function(start, end, jsEvent, view, resource) {
console.log(
'select',
start.format(),
end.format(),
resource ? resource.id : '(no resource)'
);
},
dayClick: function(date, jsEvent, view, resource) {
console.log(
'dayClick',
date.format(),
resource ? resource.id : '(no resource)'
);
}
});
});
</script>
<style>
body {
margin: 0;
padding: 0;
font-family: "Lucida Grande",Helvetica,Arial,Verdana,sans-serif;
font-size: 14px;
}
#calendar {
max-width: 900px;
margin: 50px auto;
}
</style>
</head>
<body>
<div id='calendar'></div>
</body>
</html>
I also had this problem. My solution was to use this in the eventAfterAllRender callback function.
function eventAfterAllRenderCallback(){
$('.fc-agendaDay-button').click(function(){
$("#schedule_container").css('min-width',$('.fc-resource-cell').length*slot_width_resource);
}
$('.fc-resourceDay-button').click(function(){
$("#schedule_container").css('min-width','');
}
}
The slot_width_resource is the number of pixel wide you want the columns to be (I use 125). Until Fullcalendar comes out with better support this solution has worked work me
Place this function after your fullcalendar initializer and inside the initializer put the callback function like another fullcalendar option
$('#calendar').fullCalendar({
eventAfterAllRender:eventAfterAllRenderCallback,
});