Dynamic Row Span in react mantine tablle - reactjs

import { Table } from "#mantine/core";
import React from "react";
interface TableProps {
columns: ColumnProps[];
data: {
[key: string]: string | number | null;
}[];
groupBy: string;
groupedColumn: string;
}
interface ColumnProps {
key: string;
label: string;
actions?: React.ReactNode;
}
type modifiedType = { [key: string]: string | number | (string | number)[] | null };
export const RowGrouping = ({ columns, data, groupBy, groupedColumn }: TableProps) => {
const transformData = data.reduce<modifiedType[]>((modifiedObj: modifiedType[], dataObj) => {
const similar: modifiedType | undefined = modifiedObj.find((e) => e[groupBy] == dataObj[groupBy]);
const groupedKey = Object.keys(dataObj).find((key) => key.includes(groupedColumn)) ?? "";
return (
similar
? (similar[groupedKey] as (string | number | null)[]).push(dataObj[groupedKey])
: modifiedObj.push({
...dataObj,
[groupedKey]: [dataObj[groupedKey]] as (string | number)[],
}),
modifiedObj
);
}, []);
const tableHead = () => {
return (
<tr>
{columns.map((c, index) => (
<th key={index}>{c.label}</th>
))}
</tr>
);
};
const tableData = () => {
return (
<>
{transformData.map((c, index) => (
<>
<tr key={index}>
<td rowSpan={(c[groupedColumn] as string).length + 1}>{c[groupBy]}</td>
</tr>
{(c[groupedColumn] as (string | number | null)[]).map((a: string | number | null) => (
<tr key={a}>{a?.toString().trim() == "" || a?.toString().trim() == null ? <td> </td> : <td>{a}</td>}</tr>
))}
</>
))}
</>
);
};
return (
<div>
<Table withBorder withColumnBorders>
<thead>{tableHead()}</thead>
<tbody>{tableData()}</tbody>
</Table>
</div>
);
};
Following is the Input data to the above code
columns = [
{
key: "state_name",
label: "State",
},
{
key: "district",
label: "District",
},
];
data = [
{
state_name: "Karnataka",
district: "Banglore",
gender: "Boys",
},
{
state_name: "Karnataka",
district: "Banglore",
gender: "Girls",
},
{
state_name: "Telangana",
district: null,
gender: "Boys",
},
{
state_name: "Telangana",
district: "Hyderabad",
gender: "Boys",
},
{
state_name: "Karnataka",
district: "Mysore",
gender: "Girls",
},
{
state_name: "Karnataka",
district: " ",
gender: "Boys",
},
{
state_name: "Karnataka",
district: "Manglore",
gender: "Transgender",
},
{
state_name: "Goa",
district: "North",
gender: "Girls",
},
{
state_name: "Andhra Pradesh",
district: "Chittor",
gender: "Boys",
},
{
state_name: "Andhra Pradesh",
district: "Chittor",
gender: "Girls",
},
{
state_name: "Goa",
district: "South",
gender: "Transgender",
},
{
state_name: "Andhra Pradesh",
district: "Vizag",
gender: "Boys",
},
{
state_name: "kerala",
district: "pollachi",
gender: "Boys",
},
];
groupBy = "state_name";
groupedColumn = "district";
below is the output for this code
this code is perfectly okay when there are only two columns but i want to continue to group the remaining columns also here for example gender and again if columns are added it should group them as well... im unable to do it please help and i want to do it without hardcodes. so by removing grouped column and just by giving groupby it should group all columns without altering the props but i can transform the data

Taking the rowspan and colspan values ​​in the header will tire the system less. this way you won't need to do any grouping.
columns = [
{
key: "state_name",
label: "State",
colspan:2
},
{
key: "district",
label: "District",
colspan:3
},
];
Example : `const tableData = () => data?.map((item) => (
<tr>
{columns?.map(({key,colspan,...other}) => (
<td colSpan={colspan}>
item?.[key]
</td>
))}
</tr>
))`

Related

merging the rows and displaying it in mantine table in react

import { Table } from "#mantine/core";
import React from "react";
interface TableProps {
columns: ColumnProps[];
data: {
[key: string]: string | number;
}[];
group: string[];
}
interface ColumnProps {
key: string;
label: string;
actions?: React.ReactNode;
}
export const RowGrouping = ({ columns, data, group }: TableProps) => {
columns = [
{
key: "state_name",
label: "State",
},
{
key: "district",
label: "District",
},
{
key: "gender",
label: "Gender",
},
];
data = [
{
state_name: "Karnataka",
district: "Banglore",
gender: "Boys",
},
{
state_name: "Karnataka",
district: "Banglore",
gender: "girls",
},
{
state_name: "Telangana",
district: "Hyderabad",
gender: "Boys",
},
{
state_name: "Karnataka",
district: "Mysore",
gender: "Girls",
},
{
state_name: "Karnataka",
district: "Mysore",
gender: "Boys",
},
{
state_name: "Karnataka",
district: "Manglore",
gender: "Transgender",
},
{
state_name: "Goa",
district: "North",
gender: "Girls",
},
{
state_name: "Andhra Pradesh",
district: "Chittor",
gender: "Boys",
},
{
state_name: "Andhra Pradesh",
district: "Chittor",
gender: "Girls",
},
{
state_name: "Goa",
district: "South",
gender: "Transgender",
},
{
state_name: "Andhra Pradesh",
district: "Vizag",
gender: "Boys",
},
];
group = ["state_name", "district"];
const mergeData = data.reduce((a, b) => {
const similar = a.find((e) => e.state_name == b.state_name);
return similar ? similar.district.push(b.district) : a.push({ ...b, district: [b.district] }), a;
}, []);
const tableHead = () => {
return (
<tr>
{columns.map((c, index) => (
<th key={index}>{c.label}</th>
))}
</tr>
);
};
const tableData = () => {
return (
<>
{mergeData.map((c, index) => (
<tr key={index}>
<td>{c.state_name}</td>
{c.district.map((d, i) => (
<tr key={i}>
<tr>
<td>{d}</td>
</tr>
</tr>
))}
</tr>
))}
</>
);
};
return (
<div>
<Table withBorder withColumnBorders style={{ width: "50%", margin: "0 auto", marginTop: "50px" }}>
<thead>{tableHead()}</thead>
<tbody>{tableData()}</tbody>
</Table>
</div>
);
};
Here in this example, what I'm trying to do is that I have three columns - state, district and gender, and I'm trying to group the rows and display it in table. but I'm able to group only one column that is state but I'm unable to group district wise, and I don't know how to generalize this without hardcode means data columns should be grouped for any data by column name and displayed in table.[ this is the output I'm getting but i want the districts to be displayed properly means inside karnataka rowspan there should be only banglore, mysore and manglore and inside banglore rowspan there should be boys and girls and same for mysore and chittor as well without hardcoded. please help...
You could adjust your merge fn so that it only pushes the district if it's not already in the district array.
const mergeData = data.reduce((a, b) => {
const similar = a.find((e) => e.state_name == b.state_name);
return (
similar
? !similar.district.includes(b.district) &&
similar.district.push(b.district)
: a.push({
...b,
district: [b.district],
}),
a
);
}, []);
Output :
[
{
district: ["Banglore", "Mysore", "Manglore"],
gender: "Boys",
state_name: "Karnataka",
},
{
district: ["Hyderabad"],
gender: "Boys",
state_name: "Telangana",
},
{
district: ["North", "South"],
gender: "Girls",
state_name: "Goa",
},
{
district: ["Chittor", "Vizag"],
gender: "Boys",
state_name: "Andhra Pradesh",
},
];
Fiddle : https://jsfiddle.net/RyanZee/bnh6u7mx/4/
As for the gender being displayed, you're not returning it in your map:
{
mergeData.map((c, index) => (
<tr key={index}>
<td>{c.state_name}</td>
{c.district.map((d, i) => (
<tr key={i}>
<tr>
<td>{d}</td>
</tr>
</tr>
))}
<td>{c.gender}</td>
</tr>
));
}

I am facing problem while filtering array using checkboxes using react hooks and typescript

I am trying to filter array as per gender (using checkbox ) but its not working. When i clicked on male checkbox it works but it wont work by clicking on female checkbox button. Here is my App.tsx. Need help to solve this?
import React, { useState } from "react";
const App = () => {
const [students, setStudents] = useState([
{ id: 1, title: "Akita from place1", race: "Akita", gender: 'female' },
{ id: 2, title: "Akita from place2", race: "Akita", gender: 'female' },
{ id: 3, title: "Akita from place3", race: "Akita", gender: 'female' },
{ id: 4, title: "Chihuahua from place4", race: "Chihuahua" , gender: 'male' },
{ id: 5, title: "Cockapoo from place5", race: "Cockapoo" , gender: 'male'},
{ id: 6, title: "Dachshund from place6", race: "Dachshund", gender: 'male' },
{ id: 7, title: "Dutch Shepherd from place7", race: "Dutch Shepherd" , gender: 'female' },
{ id: 8, title: "Bulldog from place8", race: "Bulldog", gender: 'male' },
{ id: 9, title: "Goldador from place9", race: "Goldador", gender: 'female' },
]);
const filterData = (e: any) => {
console.log(e.target.value);
if (e.target.value === "male") {
const filteredData = students.filter((student) => {
return student.gender === "male";
});
setStudents(filteredData);
}
if (e.target.value === "female") {
const filteredData = students.filter((student) => {
return student.gender === "female";
});
setStudents(filteredData);
}
};
return (
<div>
<h3>app</h3>
Male: <input type="checkbox" name='male' value='male' onChange={filterData} />
Female: <input type="checkbox" name='female' value='female' onChange={filterData} />
{students
.map((student: any) => {
return (
<div key={student.id}>
{student.id}-{student.title}-{student.race}-{student.gender}
</div>
);
})}
</div>
);
};
export default App;
const {
useState
} = React;
const App = () => {
const [students, setStudents] = React.useState([{
id: 1,
title: "Akita from place1",
race: "Akita",
gender: 'female'
},
{
id: 2,
title: "Akita from place2",
race: "Akita",
gender: 'female'
},
{
id: 3,
title: "Akita from place3",
race: "Akita",
gender: 'female'
},
{
id: 4,
title: "Chihuahua from place4",
race: "Chihuahua",
gender: 'male'
},
{
id: 5,
title: "Cockapoo from place5",
race: "Cockapoo",
gender: 'male'
},
{
id: 6,
title: "Dachshund from place6",
race: "Dachshund",
gender: 'male'
},
{
id: 7,
title: "Dutch Shepherd from place7",
race: "Dutch Shepherd",
gender: 'female'
},
{
id: 8,
title: "Bulldog from place8",
race: "Bulldog",
gender: 'male'
},
{
id: 9,
title: "Goldador from place9",
race: "Goldador",
gender: 'female'
},
]);
const [filtered, setFiltered] = useState([])
const filterData = (e) => {
const {value, checked} = e.target;
//check if value not in state and checked is true then add value to state
if(!filtered.includes(value) && checked){
setFiltered([...filtered, value])
}else{
setFiltered(filtered.filter(f=>f!==value))
}
};
const filteredStudent = filtered.length > 0 ? students.filter(s => filtered.includes(s.gender)) : students;
return (
<div>
<h3>app</h3>
Male: <input type="checkbox" name='male' value='male' onChange={filterData}/>
Female: <input type="checkbox" name='female' value='female' onChange={filterData}/>
{filteredStudent
.map((student) => {
return (
<div key={student.id}>
{student.id}-{student.title}-{student.race}-{student.gender}
</div>
);
})}
</div>
);
};
// Render it
ReactDOM.createRoot(
document.getElementById("root")
).render( <
App / >
);
<div id="root"></div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.1.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.1.0/umd/react-dom.development.js"></script>
It does not work because you are filtering all the female out and updating the state, this means that after clicking one button once, the filtered values does not exist in state anymore. To fix this, you could track the filter type in state and derive the filtered students during render.
Note that you could use radio buttons so only one gender can be selected at a time.
import React, {useState} from "react";
const App = () => {
const [students, setStudents] = useState([
{id: 1, title: "Akita from place1", race: "Akita", gender: 'female'},
{id: 2, title: "Akita from place2", race: "Akita", gender: 'female'},
{id: 3, title: "Akita from place3", race: "Akita", gender: 'female'},
{id: 4, title: "Chihuahua from place4", race: "Chihuahua", gender: 'male'},
{id: 5, title: "Cockapoo from place5", race: "Cockapoo", gender: 'male'},
{id: 6, title: "Dachshund from place6", race: "Dachshund", gender: 'male'},
{id: 7, title: "Dutch Shepherd from place7", race: "Dutch Shepherd", gender: 'female'},
{id: 8, title: "Bulldog from place8", race: "Bulldog", gender: 'male'},
{id: 9, title: "Goldador from place9", race: "Goldador", gender: 'female'},
]);
const [filter, setFilter] = useState<null | string>(null)
const filterData = (e) => {
setFilter(e.target.checked ? e.target.value : null)
};
const filteredStudent = filter ? students.filter(s => s.gender === filter) : students;
return (
<div>
<h3>app</h3>
Male: <input type="checkbox" name='male' value='male' onChange={filterData}/>
Female: <input type="checkbox" name='female' value='female' onChange={filterData}/>
{filteredStudent
.map((student) => {
return (
<div key={student.id}>
{student.id}-{student.title}-{student.race}-{student.gender}
</div>
);
})}
</div>
);
};
export default App;

How to use setState in functional component React?

I was using classes. I changed it to functional components. But in handleLike method. I cant seem to understand how to use setState. Anyhelp with how to do it? In my current useState im getting array of objects. When I click on like button it displays an error that movies.map is not a function. Thankyou
movies.jsx
import React, { Component, useState } from "react";
import { getMovies } from "../services/fakeMovieService";
import Like from "./like";
function Movies() {
const initialMovies = getMovies();
const [movies, setMovies] = useState(initialMovies);
const handleDelete = (movie) => {
setMovies((movies) => movies.filter((m) => m._id !== movie._id));
};
const handleLike = (movie) => {
const movies = [...movies]
const index = movies.indexOf(movie)
movies[index] = { ...movie[index]}
movies[index].liked = !movies[index].liked
setMovies({ movies })
};
const { length: count } = movies;
if (count === 0) return <p>There are no movies in database</p>;
return (
<React.Fragment>
<p> Showing {count} movies in the database</p>
<table className="table">
<thead>
<tr>
<th>Title</th>
<th>Genre</th>
<th>Stock</th>
<th>Rate</th>
<th></th>
<th></th>
</tr>
</thead>
<tbody>
{movies.map((movie) => (
<tr key={movie._id}>
<td>{movie.title}</td>
<td>{movie.genre.name}</td>
<td>{movie.numberInStock}</td>
<td>{movie.dailyRentalRate}</td>
<td>
<Like liked={movie.liked} onClick={()=> handleLike(movie)} />
</td>
<td>
<button
onClick={() => handleDelete(movie)}
className="btn btn-danger btn-sm"
>
Delete
</button>
</td>
</tr>
))}
</tbody>
</table>
</React.Fragment>
);
}
Like.jsx
class Like extends React.Component {
render() {
let classes = "fa fa-heart";
if (!this.props.liked) classes+= "-o"
return (
<i
className={classes}
aria-hidden="true"
onClick={this.props.onClick}
style={{cursor:"pointer"}}
></i>
);
}
}
JSON FILE
const movies = [
{
_id: "5b21ca3eeb7f6fbccd471815",
title: "Terminator",
genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
numberInStock: 6,
dailyRentalRate: 2.5,
publishDate: "2018-01-03T19:04:28.809Z",
liked: true,
},
{
_id: "5b21ca3eeb7f6fbccd471816",
title: "Die Hard",
genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
numberInStock: 5,
dailyRentalRate: 2.5
},
{
_id: "5b21ca3eeb7f6fbccd471817",
title: "Get Out",
genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "Thriller" },
numberInStock: 8,
dailyRentalRate: 3.5
},
{
_id: "5b21ca3eeb7f6fbccd471819",
title: "Trip to Italy",
genre: { _id: "5b21ca3eeb7f6fbccd471814", name: "Comedy" },
numberInStock: 7,
dailyRentalRate: 3.5
},
{
_id: "5b21ca3eeb7f6fbccd47181a",
title: "Airplane",
genre: { _id: "5b21ca3eeb7f6fbccd471814", name: "Comedy" },
numberInStock: 7,
dailyRentalRate: 3.5
},
{
_id: "5b21ca3eeb7f6fbccd47181b",
title: "Wedding Crashers",
genre: { _id: "5b21ca3eeb7f6fbccd471814", name: "Comedy" },
numberInStock: 7,
dailyRentalRate: 3.5
},
{
_id: "5b21ca3eeb7f6fbccd47181e",
title: "Gone Girl",
genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "Thriller" },
numberInStock: 7,
dailyRentalRate: 4.5
},
{
_id: "5b21ca3eeb7f6fbccd47181f",
title: "The Sixth Sense",
genre: { _id: "5b21ca3eeb7f6fbccd471820", name: "Thriller" },
numberInStock: 4,
dailyRentalRate: 3.5
},
{
_id: "5b21ca3eeb7f6fbccd471821",
title: "The Avengers",
genre: { _id: "5b21ca3eeb7f6fbccd471818", name: "Action" },
numberInStock: 7,
dailyRentalRate: 3.5
}
];
export function getMovies() {
return movies;
}
You have a few redundant object/array assignment in your code
So, update your handleLike like so:
const handleLike = (movie) => {
const _movies = [...movies];
const index = movies.indexOf(movie);
_movies[index].liked = !movies[index].liked;
setMovies(_movies);
};
Working Example:

Can I initialize the checkbox selection in MUI DataGrid?

In a MUI DataGrid it is super easy to add a checkbox selection via the checkboxSelection attribute and listen to selection changes via onSelectionChange:
<DataGrid
columns={columns}
rows={rows}
pageSize={10}
checkboxSelection
onSelectionChange={e => console.log(e.rows)}
/>
But is there also a way to initialize the checkbox selection with a set of checked items?
Currently the DataGrid doesn't have a way to set the default selectionModel (something like defaultSelectionModel prop), so in order to set the default selected rows, you need to use controlled mode by adding selectionModel/onSelectionModelChange and pass the initial value in useState. It's an ID array of the rows you wish to select at the start.
const rows = [
{ id: 1, lastName: "Snow", firstName: "Jon", age: 35 },
{ id: 2, lastName: "Lannister", firstName: "Cersei", age: 42 },
{ id: 3, lastName: "Lannister", firstName: "Jaime", age: 45 },
{ id: 4, lastName: "Stark", firstName: "Arya", age: 16 },
{ id: 5, lastName: "Targaryen", firstName: "Daenerys", age: null },
{ id: 6, lastName: "Melisandre", firstName: null, age: 150 },
{ id: 7, lastName: "Clifford", firstName: "Ferrara", age: 44 },
{ id: 8, lastName: "Frances", firstName: "Rossini", age: 36 },
{ id: 9, lastName: "Roxie", firstName: "Harvey", age: 65 }
];
function MyDataGrid() {
const [selectionModel, setSelectionModel] = React.useState(() =>
rows.filter((r) => r.age > 40).map((r) => r.id),
);
return (
<div style={{ height: 400, width: '100%' }}>
<DataGrid
checkboxSelection
rows={rows}
columns={columns}
selectionModel={selectionModel}
onSelectionModelChange={setSelectionModel}
/>
</div>
);
}
Live Demo
The DataGrid has a selectionModel property that accepts an array of row IDs.
<DataGrid
columns={columns}
rows={rows}
pageSize={10}
checkboxSelection
onSelectionChange={e => console.log(e.rows)}
selectionModel={[rowId1, rowId2, rowId3]}
/>
import * as React from "react";
import {
DataGrid,
RowData,
useRows,
useApiRef,
GridApi,
} from "#material-ui/data-grid";
import { useDemoData } from "#material-ui/x-grid-data-generator";
let i = 0;
export default function ControlledSelectionGrid() {
const apiRef = React.useRef(null);
console.log("apiRef:", apiRef);
const ObjRef = React.useRef({
dataRe:{
columns:[],
rows:[]
}
})
const counterRef = React.useRef({
renderCount:0
})
// TODO: https://github.com/mui-org/material-ui-x/issues/246
const [selection, setSelection] = React.useState([]);
const columns = [
{ field: "id", headerName: "ID", width: 70 },
{ field: "firstName", headerName: "First name", width: 130 },
{ field: "lastName", headerName: "Last name", width: 130 },
{
field: "age",
headerName: "Age",
type: "number",
width: 90,
},
{
field: "fullName",
headerName: "Full name",
description: "This column has a value getter and is not sortable.",
sortable: false,
width: 160,
valueGetter: (params) =>
`${params.getValue("firstName") || ""} ${
params.getValue("lastName") || ""
}`,
},
];
const rows = [
{ id: 1, lastName: "Snow", firstName: "Jon", age: 35 },
{ id: 2, lastName: "Lannister", firstName: "Cersei", age: 42 },
{ id: 3, lastName: "Lannister", firstName: "Jaime", age: 45 },
{ id: 4, lastName: "Stark", firstName: "Arya", age: 16 },
{ id: 5, lastName: "Targaryen", firstName: "Daenerys", age: null },
{ id: 6, lastName: "Melisandre", firstName: null, age: 150 },
{ id: 7, lastName: "Clifford", firstName: "Ferrara", age: 44 },
{ id: 8, lastName: "Frances", firstName: "Rossini", age: 36 },
{ id: 9, lastName: "Roxie", firstName: "Harvey", age: 65 },
];
//console.log('dataRe out:',ObjRef.current.dataRe)
React.useEffect(() => {
const dataRe = {
columns,
rows
}
ObjRef.current.dataRe = dataRe
counterRef.current.renderCount +=1
console.log('no of render**:',counterRef.current.renderCount)
console.log('apiRef.current**:',apiRef.current)
//console.log('in useEffect..')
const rowModels = apiRef?.current?.getRowModels();
console.log("rowModels:", rowModels);
console.log('dataRe',dataRe)
if (rowModels!=undefined) {
if(apiRef.current){
apiRef.current.setRowModels(
rowModels.map((r) => {
//console.log("rowModel row:", r);
r.selected = r.data.age > 40;
return r;
})
);
}
}
},[apiRef.current]);
return (
<div style={{ height: 400, width: "100%" }}>
<DataGrid
checkboxSelection
onSelectionChange={(newSelection) => {
setSelection(newSelection.rows);
}}
components={{
noRowsOverlay: (params) => {
//console.log('params in noRowsOverlay:',params)
if (!apiRef.current) {
//console.log('in apiRef current noRowsOverlay')
apiRef.current = params.api.current;
//console.log('apiRef.current in noRowOverlay:',apiRef.current)
}
return <div>No rows</div>;
},
}}
{...ObjRef.current.dataRe}
/>
</div>
);
}

Selected value is not displayed in async mode

I've got a react-select that I'm populating asyncly. The items display just fine however, after an item is selected the list reverts to Loading..., the spinner starts spinning and nothing appears in the select box.
I can only guess the selected value is not being persisted?? not sure. Complete=true in autocompleteLoad() has no affect. Setting isLoading=false has no affect. Here's the code...
import * as React from 'react';
import { RouteComponentProps } from 'react-router';
import * as models from '../models'
import Select from 'react-select'
import 'react-select/dist/react-select.css'
interface MovieActorState {
actor: models.Actor[]
loading: boolean
activeMovieId: number
activeActorId: number
acLoading: boolean,
acLabel?: string
}
const data = [{ value: 1, label: 'Mr Holland\'s Opus' },
{ value: 2, label: 'Braveheart' },
{ value: 3, label: 'Batman Forever' },
{ value: 1004, label: 'Star Wars' },
{ value: 1005, label: 'Goonies' },
{ value: 1006, label: 'ET' }];
const actors = [{ Id: 1, Name: 'Mel Gibson', Gender: 'Male', Age: 54, Picture: null },
{ Id: 2, Name: 'Val Kilmar', Gender: 'Male', Age: 49, Picture: null },
{ Id: 3, Name: 'Micheal Keaton', Gender: 'Male', Age: 60, Picture: null },
{ Id: 1002, Name: 'Diane Keaton', Gender: 'Female', Age: 49, Picture: null },
{ Id: 1003, Name: 'Tom Cruise', Gender: 'Male', Age: 55, Picture: null },
{ Id: 1006, Name: 'Richard Simmons', Gender: 'Male', Age: 59, Picture: null }];
const movieactors = [{ MovieId: 1, ActorId: 1 },
{ MovieId: 1, ActorId: 2 },
{ MovieId: 1, ActorId: 3 }];
export class Test extends React.Component<RouteComponentProps<{}>, MovieActorState> {
constructor(props) {
super(props);
this.that = this;
this.state = {
actor: [],
loading: true,
activeMovieId: 0,
activeActorId: 0,
acLoading: false
};
console.log('movieactor.fetch()', this.state)
this.setState({
actor: actors,
loading: false,
});
}
that;
public render() {
console.log('movieactor.render', this.state)
let contents = this.state.loading
? <p><em>Loading...</em></p>
: this.renderTable(this.state.actor, true);
return <div>
<h1>MovieActor</h1>
<label>Movie</label>
<Select.Async
name="form-field-name"
loadOptions={this.autocompleteLoad}
valueKey="value"
labelKey="label"
onChange={this.autocompleteSelect.bind(this)}
placeholder="Type to search"
value={this.state.activeMovieId + ''}
isLoading={false}
onClose={this.autocompleteClose.bind(this)}
/><br />
{contents}
</div>;
}
autocompleteSelect(e) {
console.log('movieactor.autocompleteSelect()', e, this.state)
this.setState({
actor: actors.filter((actor) => {
return (actor.Id > e.value);
}),
loading: false,
activeMovieId: e.value,
acLoading: false,
acLabel: e.label
});
}
autocompleteClose(e) {
console.log('movieactor.autocompleteClose()', e, this.state)
this.setState({ acLoading: false });
}
autocompleteLoad(input, callback) {
console.log('autocompleteLoad(' + input + ')')
if (input == null || input.length == 0) {
console.log('null')
callback(null, { complete: true })
return;
}
callback(null, {
options: data, complete: true
})
};
private renderTable(actor: models.Actor[], allowSort: boolean = false) {
let headings = this.renderTableHeadings(allowSort)
return <table className='table'>
<thead>
{headings}
</thead>
<tbody>
{actor.map(item =>
<tr key={item.Id}>
<td>
</td>
<td>{item.Id}</td>
<td>{item.Name}</td>
<td>{item.Gender}</td>
<td>{item.Age}</td>
<td>{item.Picture}</td>
</tr>
)}
</tbody>
</table>;
}
private renderTableHeadings(allowSort: boolean) {
return <tr>
<th></th>
<th>Id</th>
<th>Name</th>
<th>Gender</th>
<th>Age</th>
<th>Picture</th>
</tr>
}
}
Update: In my on-going effort to get this to work, it seems the hidden input with the value is missing. According to the react-select docs:
..but when I inspect the dom (after selecting item) it's not there...
I'm going to give this another day, before I replace the component with something else.
Code is working 100% fine,
Please check the WORKING DEMO , there might be some other code that would be affecting issue.

Resources