Related
my current code shows a complete list of clinics, when in the selector I choose a province, it shows me the clinics located in that province, what I would like is not to show the complete list of clinics at the beginning but only show the result when filtering by province. That is to say, when starting the application that only the selection is seen and once the province is selected, the results will be shown.
import React, { useState, useEffect } from 'react'
import Select, { SingleValue } from 'react-select'
import { getClinic } from '../../api/drupalAPI'
import {Clinic} from '#icofcv/common';
export const SearchFilterClinics = () => {
////filter
type OptionType = {
value: string;
label: string;
};
const provincesList: OptionType[] = [
{ value: 'Todos', label: 'Todos' },
{ value: 'Alava/Araba', label: 'Alava/Araba' },
{ value: 'Albacete', label: 'Albacete' },
{ value: 'Alicante', label: 'Alicante' },
{ value: 'Almería', label: 'Almería' },
{ value: 'Avila', label: 'Avila' },
{ value: ' Badajoz', label: ' Badajoz' },
{ value: 'Islas Baleares', label: 'Islas Baleares' },
{ value: 'Barcelona', label: 'Barcelona' },
{ value: 'Burgos', label: 'Burgos' },
{ value: 'Cáceres', label: 'Cáceres' },
{ value: 'Cádiz', label: 'Cádiz' },
{ value: 'Castellón', label: 'Castellón' },
{ value: 'Ciudad Real', label: 'Ciudad Real' },
{ value: 'Córdoba', label: 'Córdoba' },
{ value: 'A Coruña/La Coruña', label: 'A Coruña/La Coruña' },
{ value: 'Cuenca', label: 'Cuenca' },
{ value: 'Gerona/Girona', label: 'Gerona/Girona' },
{ value: 'Granada', label: 'Granada' },
{ value: 'Guadalajara', label: 'Guadalajara' },
{ value: 'Gipuzkoa/Guipuzcoa', label: 'Gipuzkoa/Guipuzcoa' },
{ value: 'Huelva', label: 'Huelva' },
{ value: 'Huesca', label: 'Huesca' },
{ value: 'Jaen', label: 'Jaen' },
{ value: 'León', label: 'León' },
{ value: 'Lérida/Lleida', label: 'Lérida/Lleida' },
{ value: 'La Rioja', label: 'La Rioja' },
{ value: 'Lugo', label: 'Lugo' },
{ value: 'Madrid', label: 'Madrid' },
{ value: ' Málaga', label: ' Málaga' },
{ value: 'Murcia', label: 'Murcia' },
{ value: 'Navarra', label: 'Navarra' },
{ value: 'Orense/Ourense', label: 'Orense/Ourense' },
{ value: 'Asturias', label: 'Asturias' },
{ value: 'Palencia', label: 'Palencia' },
{ value: 'Las Palmas', label: 'Las Palmas' },
{ value: 'Pontevedra', label: 'Pontevedra' },
{ value: 'Salamanca', label: 'Salamanca' },
{ value: 'S.C.Tenerife', label: 'S.C.Tenerife' },
{ value: 'Cantabria', label: 'Cantabria' },
{ value: 'Segovia', label: 'Segovia' },
{ value: ' Sevilla', label: ' Sevilla' },
{ value: 'Soria', label: 'Soria' },
{ value: 'Tarragona', label: 'Tarragona' },
{ value: 'Teruel', label: 'Teruel' },
{ value: 'Toledo', label: 'Toledo' },
{ value: 'Valencia', label: 'Valencia' },
{ value: 'Valladolid', label: 'Valladolid' },
{ value: 'Bizkaia/Vizcaya', label: 'Bizkaia/Vizcaya' },
{ value: 'Zamora', label: 'Zamora' },
{ value: 'Zaragoza', label: 'Zaragoza' },
{ value: 'Ceuta', label: 'Ceuta' },
{ value: 'Melilla', label: 'Melilla' },
]
const [clinicList, setClinicList] = useState<Clinic[]>([]);
const [clinicListFilteredSelect, setClinicListFilteredSelect] = useState<Clinic[]>([]);
const [filterSelectClinic, setFilterSelectClinic] = useState<SingleValue<OptionType>>(provincesList[0]);
const fetchClinicList = async () => {
getClinic().then((response)=>{
console.log(response)
setClinicList(response);
setClinicListFilteredSelect(response)
}).catch ( (error) => {
console.error(error);
throw error;
});
}
const handleChangeSelect = (provinceList: SingleValue<OptionType>) =>{
console.log(provinceList)
setFilterSelectClinic(provinceList);
filterSelect(provinceList );
}
const filterSelect=(termSearch)=>{
const resultFilterSelect = clinicList.filter((element) => {
if(element.province?.toString().toLowerCase().includes(termSearch.value.toLowerCase() )
){
return element;
}
});
setClinicListFilteredSelect(resultFilterSelect);
}
useEffect (() => {
fetchClinicList();
}, []);
return (
<>
<div>
<h1>Encuentra tu clínica</h1>
</div>
<div>
<Select
defaultValue={filterSelectClinic}
options={provincesList}
onChange={handleChangeSelect}
/>
{
clinicListFilteredSelect.map((clinic) => (
<div>
<div>{clinic.title}</div>
<div>{clinic.propsPhone}</div>
<div>{clinic.mobile}</div>
<div>{clinic.email}</div>
<div>{clinic.province} </div>
<div>{clinic.registry}</div>
</div>
))
}
</div>
</>
)
}
You're setting clinicListFilteredSelect in your useEffect with an empty dependancy array. This means when your component mounts it will set clinicListFilteredSelect to the response of your API call.
If you instead want to only show the response when filterting by clinics, you need to move this call to the event handler and remove the useEffect.
Something like:
const handleChangeSelect = async (provinceList: SingleValue<OptionType>) => {
getClinic().then((response) => {
setClinicList(response);
setClinicListFilteredSelect(response)
setFilterSelectClinic(provinceList);
filterSelect(provinceList );
}).catch ((error) => {
console.error(error);
throw error;
});
}
I have a problem regarding highcharts organization in reactjs/nextjs. I installed the npm package of highcharts-react-official and highcharts and import it in my component, still it gives me error that the organization is a missing module.
Here is the error:
Error: Highcharts error #17: www.highcharts.com/errors/17/?missingModuleFor=organization
- missingModuleFor: organization
Here is what I've tried .
import { useState } from "react";
import Highcharts from "highcharts";
import HighchartsReact from "highcharts-react-official";
const HighChartsRender = () => {
const options = {
title: {
text: "My chart",
},
accessibility: {
point: {
descriptionFormatter: function (point) {
var nodeName = point.toNode.name,
nodeId = point.toNode.id,
nodeDesc = nodeName === nodeId ? nodeName : nodeName + ', ' + nodeId,
parentDesc = point.fromNode.id;
return point.index + '. ' + nodeDesc + ', reports to ' + parentDesc + '.';
}
}
},
series: [{
type: 'organization',
name: 'Highsoft',
keys: ['from', 'to'],
data: [
['Shareholders', 'Board'],
['Board', 'CEO'],
['CEO', 'CTO'],
['CEO', 'CPO'],
['CEO', 'CSO'],
['CEO', 'HR'],
['CTO', 'Product'],
['CTO', 'Web'],
['CSO', 'Sales'],
['HR', 'Market'],
['CSO', 'Market'],
['HR', 'Market'],
['CTO', 'Market']
],
levels: [{
level: 0,
color: 'silver',
dataLabels: {
color: 'black'
},
height: 25
}, {
level: 1,
color: 'silver',
dataLabels: {
color: 'black'
},
height: 25
}, {
level: 2,
color: '#980104'
}, {
level: 4,
color: '#359154'
}],
nodes: [{
id: 'Shareholders'
}, {
id: 'Board'
}, {
id: 'CEO',
title: 'CEO',
name: 'Grethe Hjetland',
image: 'https://wp-assets.highcharts.com/www-highcharts-com/blog/wp-content/uploads/2020/03/17131126/Highsoft_03862_.jpg'
}, {
id: 'HR',
title: 'HR/CFO',
name: 'Anne Jorunn Fjærestad',
color: '#007ad0',
image: 'https://wp-assets.highcharts.com/www-highcharts-com/blog/wp-content/uploads/2020/03/17131210/Highsoft_04045_.jpg'
}, {
id: 'CTO',
title: 'CTO',
name: 'Christer Vasseng',
image: 'https://wp-assets.highcharts.com/www-highcharts-com/blog/wp-content/uploads/2020/03/17131120/Highsoft_04074_.jpg'
}, {
id: 'CPO',
title: 'CPO',
name: 'Torstein Hønsi',
image: 'https://wp-assets.highcharts.com/www-highcharts-com/blog/wp-content/uploads/2020/03/17131213/Highsoft_03998_.jpg'
}, {
id: 'CSO',
title: 'CSO',
name: 'Anita Nesse',
image: 'https://wp-assets.highcharts.com/www-highcharts-com/blog/wp-content/uploads/2020/03/17131156/Highsoft_03834_.jpg'
}, {
id: 'Product',
name: 'Product developers'
}, {
id: 'Web',
name: 'Web devs, sys admin'
}, {
id: 'Sales',
name: 'Sales team'
}, {
id: 'Market',
name: 'Marketing team',
column: 5
}],
colorByPoint: false,
color: '#007ad0',
dataLabels: {
color: 'white'
},
borderColor: 'white',
nodeWidth: 65
}],
tooltip: {
outside: true
},
exporting: {
allowHTML: true,
sourceWidth: 800,
sourceHeight: 600
}
};
return (
<div id="wrapper">
<div className="content-area">
<HighchartsReact highcharts={Highcharts} options={options} />
</div>
</div>
);
};
export default HighChartsRender;
anyone tried to use the organization chart from highcharts in reactjs/nextjs ? .
Notice that the organization series requires two additional modules:
<script src="https://code.highcharts.com/modules/sankey.js"></script>
<script src="https://code.highcharts.com/modules/organization.js"></script>
API: https://api.highcharts.com/highcharts/series.organization
You need to import those modules and initialize them: https://stackblitz.com/edit/react-3gu5bv?file=index.js
API: https://github.com/highcharts/highcharts-react
After entering the color name in the input field, when I submit the form, an error occurs :
TypeError: Cannot read property 'toLowerCase' of undefined
(anonymous function)
C:/Users/HP/Documents/WDB/React/Practice/colors-app/src/NewPaletteForm.js:117
114 | //to check -> is 'palette name' unique
115 | ValidatorForm.addValidationRule("isPaletteNameUnique", value => {
116 | return palettes.every(
> 117 | ({ paletteName }) => paletteName.toLowerCase() !== value.toLowerCase()
118 | ^ );
119 | });
120 | })
App.js : (Class-based component)
class App extends Component {
constructor(props) {
super(props);
this.state = { palettes: seedColors };
this.findPalette = this.findPalette.bind(this);
this.savePalette = this.savePalette.bind(this);
}
savePalette(newPalette) {
this.setState({ palettes: [...this.state.palettes, newPalette] });
}
render() {
return (
<Switch>
<Route
exact
path='/palette/new'
render={(routeProps) =>
<NewPaletteForm
savePalette={this.savePalette}
palettes={this.state.palettes}
{...routeProps}
/>}
/>
NewPaletteForm.js : (Functional component and uses react hooks)
function NewPaletteForm(props) {
const classes = useStyles();
const [open, setOpen] = useState(false);
const [currentColor, setCurrentColor] = useState('teal');
const [colors, setColors] = useState([{ color: 'pink', name: 'pink' }]);
const [fields, setFields] = useState({
newColorName: '',
newPaletteName: ''
})
useEffect(() => {
ValidatorForm.addValidationRule('isColorNameUnique', (value) => {
return colors.every(
({ name }) => name.toLowerCase() !== value.toLowerCase()
);
});
ValidatorForm.addValidationRule('isColorUnique', (value) => {
return colors.every(
({ color }) => color !== currentColor
);
});
ValidatorForm.addValidationRule("isPaletteNameUnique", value => {
return props.palettes.every(
({ paletteName }) => paletteName.toLowerCase() !== value.toLowerCase()
);
});
})
function addNewColor() {
const newColor = {
color: currentColor,
name: fields.newColorName
}
setColors(oldColors => [...oldColors, newColor]);
setFields({ newColorName: '' });
};
function handleChange(evt) {
setFields({ ...fields, [evt.target.name]: evt.target.value });
}
function handleSubmit() {
let newName = fields.newPaletteName;
const newPalette = {
paletteName: newName,
id: newName.toLowerCase().replace(/ /g, '-'),
colors: colors
}
props.savePalette(newPalette);
props.history.push('/');
}
Validator form components for colors and palettes :
<ValidatorForm onSubmit={handleSubmit}>
<TextValidator
label='Palette Name'
value={fields.newPaletteName}
name='newPaletteName'
onChange={handleChange}
validators={['required', 'isPaletteNameUnique']}
errorMessages={['Enter Palette Name', 'Name already used']} />
<Button variant='contained' color='primary' type='submit'>
Save Palette
</Button>
</ValidatorForm>
<ValidatorForm onSubmit={addNewColor}>
<TextValidator
value={fields.newColorName}
name='newColorName'
onChange={handleChange}
validators={['required', 'isColorNameUnique', 'isColorUnique']}
errorMessages={['Enter a color name', 'Color name must be unique', 'Color already used!']}
/>
<Button
variant='contained'
type='submit'
color='primary'
style={{
backgroundColor: currentColor
}}
>
Add Color
</Button>
</ValidatorForm>
seedColors.js:
export default [
{
paletteName: "Material UI Colors",
id: "material-ui-colors",
emoji: "🎨",
colors: [
{ name: "red", color: "#F44336" },
{ name: "pink", color: "#E91E63" },
{ name: "purple", color: "#9C27B0" },
{ name: "deeppurple", color: "#673AB7" },
{ name: "indigo", color: "#3F51B5" },
{ name: "blue", color: "#2196F3" },
{ name: "lightblue", color: "#03A9F4" },
{ name: "cyan", color: "#00BCD4" },
{ name: "teal", color: "#009688" },
{ name: "green", color: "#4CAF50" },
{ name: "lightgreen", color: "#8BC34A" },
{ name: "lime", color: "#CDDC39" },
{ name: "yellow", color: "#FFEB3B" },
{ name: "amber", color: "#FFC107" },
{ name: "orange", color: "#FF9800" },
{ name: "deeporange", color: "#FF5722" },
{ name: "brown", color: "#795548" },
{ name: "grey", color: "#9E9E9E" },
{ name: "bluegrey", color: "#607D8B" }
]
},
{
paletteName: "Flat UI Colors v1",
id: "flat-ui-colors-v1",
emoji: "🤙",
colors: [
{ name: "Turquoise", color: "#1abc9c" },
{ name: "Emerald", color: "#2ecc71" },
{ name: "PeterRiver", color: "#3498db" },
{ name: "Amethyst", color: "#9b59b6" },
{ name: "WetAsphalt", color: "#34495e" },
{ name: "GreenSea", color: "#16a085" },
{ name: "Nephritis", color: "#27ae60" },
{ name: "BelizeHole", color: "#2980b9" },
{ name: "Wisteria", color: "#8e44ad" },
{ name: "MidnightBlue", color: "#2c3e50" },
{ name: "SunFlower", color: "#f1c40f" },
{ name: "Carrot", color: "#e67e22" },
{ name: "Alizarin", color: "#e74c3c" },
{ name: "Clouds", color: "#ecf0f1" },
{ name: "Concrete", color: "#95a5a6" },
{ name: "Orange", color: "#f39c12" },
{ name: "Pumpkin", color: "#d35400" },
{ name: "Pomegranate", color: "#c0392b" },
{ name: "Silver", color: "#bdc3c7" },
{ name: "Asbestos", color: "#7f8c8d" }
]
}
]
What you can do is check to see if the value exists before calling toLowerCase.
Try using ?., like this
Instead of using value.toLowerCase() use value?.toLowerCase().
That way if the value is undefined or null, it won't call toLowerCase()
If paletteName is the one failing you can use paletteName?.toLowerCase()
If you want to go completely safe you do
paletteName?.toLowerCase() !== value?.toLowerCase()
When I try to update the state on the hover event, the actual state value is getting changed but the graph is not re-rendering.
in the console, I am able to see the node label is changed to sample. but the graph is not rerendering.
Here is my react function based component.
import React, { useEffect, useState } from 'react';
import Graph from 'react-graph-vis';
import './vis-network.css';
function RelationGraph1() {
const [graph, setGraph] = useState({
nodes: [
{
id: 1,
label: 'Node 1',
title: '',
},
{ id: 2, label: 'Node 2', title: '' },
{ id: 3, label: 'Node 3', title: '' },
{ id: 4, label: 'Node 4', title: '' },
{ id: 5, label: 'Node 5', title: '' },
],
edges: [
{ from: 1, to: 2 },
{ from: 1, to: 3 },
{ from: 2, to: 4 },
{ from: 2, to: 5 },
],
});
const options = {
layout: {
hierarchical: false,
},
edges: {
color: '#1D1D1D',
},
interaction: {
hover: true,
navigationButtons: true,
tooltipDelay: 0,
},
nodes: {
borderWidth: 0,
borderWidthSelected: 0,
color: '#0262C4',
shape: 'circle',
size: 1,
shadow: {
enabled: true,
color: 'rgba(0,0,0,0.5)',
size: 10,
x: 5,
y: 5,
},
font: {
color: '#fff',
size: 13,
bold: {
mod: 'bold',
},
},
},
};
const events = {
select: function (event) {
var { nodes, edges } = event;
console.log('Selected nodes:');
console.log(nodes);
console.log('Selected edges:');
console.log(edges);
},
showPopup: (id) => { // node id
const data = graph.nodes.map((el) => {
if (el.id === id) {
el.label = `sample node name`;
}
return el;
});
setGraph({ ...graph, nodes: data });
},
};
return (
<Graph
graph={graph}
options={options}
events={events}
style={{ height: '450px' }}
/>
);
}
export default RelationGraph1;
Really Appriciate for the help. Thanks !
I was able to update the label in hoverNode event like this:
hoverNode: (e) => {
const data = graph.nodes.map((el) => {
if (el.id === e.node) return { ...el, label: "sample node name" };
else return el;
});
const temp = { ...graph };
temp.nodes = data;
setGraph(temp);
},
Sample: https://codesandbox.io/s/long-bird-4h444?file=/src/App.js:1235-1501
Looking forward for any hint how to style new material ui v1 autocomplete or how to pass props to it.
Here's a codesandbox code (working example):
https://codesandbox.io/s/xrzq940854
In my particular case - I would like to style the label (which goes up after entering some value into input) and that horizontal line (underline under the input value).
Thank u for any help. (dropping code also in the snippet)
P.S. I got also a question how to pass props to the styles function. If anyone knows, please let me know :)
import React from 'react';
import PropTypes from 'prop-types';
import Autosuggest from 'react-autosuggest';
import match from 'autosuggest-highlight/match';
import parse from 'autosuggest-highlight/parse';
import TextField from 'material-ui/TextField';
import Paper from 'material-ui/Paper';
import { MenuItem } from 'material-ui/Menu';
import { withStyles } from 'material-ui/styles';
const suggestions = [
{ label: 'Afghanistan' },
{ label: 'Aland Islands' },
{ label: 'Albania' },
{ label: 'Algeria' },
{ label: 'American Samoa' },
{ label: 'Andorra' },
{ label: 'Angola' },
{ label: 'Anguilla' },
{ label: 'Antarctica' },
{ label: 'Antigua and Barbuda' },
{ label: 'Argentina' },
{ label: 'Armenia' },
{ label: 'Aruba' },
{ label: 'Australia' },
{ label: 'Austria' },
{ label: 'Azerbaijan' },
{ label: 'Bahamas' },
{ label: 'Bahrain' },
{ label: 'Bangladesh' },
{ label: 'Barbados' },
{ label: 'Belarus' },
{ label: 'Belgium' },
{ label: 'Belize' },
{ label: 'Benin' },
{ label: 'Bermuda' },
{ label: 'Bhutan' },
{ label: 'Bolivia, Plurinational State of' },
{ label: 'Bonaire, Sint Eustatius and Saba' },
{ label: 'Bosnia and Herzegovina' },
{ label: 'Botswana' },
{ label: 'Bouvet Island' },
{ label: 'Brazil' },
{ label: 'British Indian Ocean Territory' },
{ label: 'Brunei Darussalam' },
];
function renderInput(inputProps) {
const { classes, autoFocus, value, ref, ...other } = inputProps;
return (
<TextField
autoFocus={autoFocus}
className={classes.textField}
value={value}
inputRef={ref}
label="Country"
InputProps={{
classes: {
input: classes.input,
},
...other,
}}
/>
);
}
function renderSuggestion(suggestion, { query, isHighlighted }) {
const matches = match(suggestion.label, query);
const parts = parse(suggestion.label, matches);
return (
<MenuItem selected={isHighlighted} component="div">
<div>
{parts.map((part, index) => {
return part.highlight ? (
<span key={String(index)} style={{ fontWeight: 300 }}>
{part.text}
</span>
) : (
<strong key={String(index)} style={{ fontWeight: 500 }}>
{part.text}
</strong>
);
})}
</div>
</MenuItem>
);
}
function renderSuggestionsContainer(options) {
const { containerProps, children } = options;
return (
<Paper {...containerProps} square>
{children}
</Paper>
);
}
function getSuggestionValue(suggestion) {
return suggestion.label;
}
function getSuggestions(value) {
const inputValue = value.trim().toLowerCase();
const inputLength = inputValue.length;
let count = 0;
return inputLength === 0
? []
: suggestions.filter(suggestion => {
const keep =
count < 5 && suggestion.label.toLowerCase().slice(0, inputLength) === inputValue;
if (keep) {
count += 1;
}
return keep;
});
}
const styles = theme => ({
container: {
flexGrow: 1,
position: 'relative',
height: 200,
},
suggestionsContainerOpen: {
position: 'absolute',
marginTop: theme.spacing.unit,
marginBottom: theme.spacing.unit * 3,
left: 0,
right: 0,
},
suggestion: {
display: 'block',
},
suggestionsList: {
margin: 0,
padding: 0,
listStyleType: 'none',
},
textField: {
width: '100%',
},
label: {
color: 'yellow',
}
});
class IntegrationAutosuggest extends React.Component {
state = {
value: '',
suggestions: [],
};
handleSuggestionsFetchRequested = ({ value }) => {
this.setState({
suggestions: getSuggestions(value),
});
};
handleSuggestionsClearRequested = () => {
this.setState({
suggestions: [],
});
};
handleChange = (event, { newValue }) => {
this.setState({
value: newValue,
});
};
render() {
const { classes } = this.props;
return (
<Autosuggest
theme={{
container: classes.container,
suggestionsContainerOpen: classes.suggestionsContainerOpen,
suggestionsList: classes.suggestionsList,
suggestion: classes.suggestion,
}}
renderInputComponent={renderInput}
suggestions={this.state.suggestions}
onSuggestionsFetchRequested={this.handleSuggestionsFetchRequested}
onSuggestionsClearRequested={this.handleSuggestionsClearRequested}
renderSuggestionsContainer={renderSuggestionsContainer}
getSuggestionValue={getSuggestionValue}
renderSuggestion={renderSuggestion}
inputProps={{
autoFocus: true,
classes,
placeholder: 'Search a country (start with a)',
value: this.state.value,
onChange: this.handleChange,
}}
/>
);
}
}
IntegrationAutosuggest.propTypes = {
classes: PropTypes.object.isRequired,
};
export default withStyles(styles)(IntegrationAutosuggest);
Material-UI v1 uses React-autosuggest module.
Check the below link
https://github.com/moroshko/react-autosuggest/blob/master/src/Autosuggest.js