Related
I have this problem where every time a user hovers there mouse pointer over my map of the USA, the map renders again. (Visually, it flashes on the screen and it looks terrible).
This is because I have an 'entityRolloever' event which causes a state variable to change.
entityRollover: function(event, data){
setHoveredState(data.label)
}
How I understand it is, when a React component (i.e. my map) changes state, it re-renders.
But what I want is, when a user hovers over a U.S. State, I want the state that is being hovered over to show up in a separate text box (without the whole map re-rendering).
I have searched around, and I have found some other React hooks which could solve this. They are useRef, useMemo, and useCallback. However, I'm not sure how they would solve my problem as I have never used them before.
If you want to recreate my problem, create a basic React app
npx create-react-app
Install the following packages
npm i fusioncharts react-fusioncharts fusionmaps
Then grab the code in my jsfiddle and paste it into 'App.js'
https://jsfiddle.net/cmascardo5/s8trame5/
There are a couple of ways to resolve this issue. I chose to replace useState() hook with useRef() since it matches your case perfectly.
useState() is a hook used in functional components to re-render components on state change, but in your case this is NOT something that we want. We want to track the updates without re-rendering the components. To achieve this, we use useRef(). When we use useRef() for the updates it will not fire re-rendering unlike useState().
In your code, I commented out the {hoveredState} you had to avoid re-rendering. Then I created a p element and ref it with useRef(). Then on the entityRollove method, I update the innerText of the referenced p element. This way we are tracking the updates without re-rendering. It is simpler to see the code, I did comment on the lines I added: (paste it in your App.js)
import React from 'react';
import './App.css';
import ReactFC from 'react-fusioncharts';
import FusionCharts from 'fusioncharts';
import FusionMaps from 'fusioncharts/fusioncharts.maps';
import USA from 'fusionmaps/maps/fusioncharts.usa';
import FusionTheme from 'fusioncharts/themes/fusioncharts.theme.fusion';
import { Grid, Paper } from '#material-ui/core';
import { useState } from 'react';
import { useRef } from 'react';
ReactFC.fcRoot(FusionCharts, FusionMaps, USA, FusionTheme);
export default function App({}) {
const [hoveredState, setHoveredState] = useState('All States');
let test1 = 'test';
// const hoveredState =useRef("All states");
// Here we are using UseRef() to get a reference to an element we want to use to show each State's names
const paragraphEl = useRef(null);
const colorrange = {
minvalue: '20',
code: '#00A971',
gradient: '1',
color: [
{
minvalue: '20',
maxvalue: '40',
code: '#EFD951',
},
{
minvalue: '40',
maxvalue: '60',
code: '#FD8963',
},
{
minvalue: '60',
maxvalue: '80',
code: '#D60100',
},
],
};
const data = [
{
id: 'HI',
value: '70.0',
},
{
id: 'DC',
value: '52.3',
},
{
id: 'MD',
value: '54.2',
},
{
id: 'DE',
value: '55.3',
},
{
id: 'RI',
value: '50.1',
},
{
id: 'WA',
value: '48.3',
},
{
id: 'OR',
value: '48.4',
},
{
id: 'CA',
value: '59.4',
},
{
id: 'AK',
value: '26.6',
},
{
id: 'ID',
value: '44.4',
},
{
id: 'NV',
value: '49.9',
},
{
id: 'AZ',
value: '60.3',
},
{
id: 'MT',
value: '42.7',
},
{
id: 'WY',
value: '42.0',
},
{
id: 'UT',
value: '48.6',
},
{
id: 'CO',
value: '45.1',
},
{
id: 'NM',
value: '53.4',
},
{
id: 'ND',
value: '40.4',
},
{
id: 'SD',
value: '45.2',
},
{
id: 'NE',
value: '48.8',
},
{
id: 'KS',
value: '54.3',
},
{
id: 'OK',
value: '59.6',
},
{
id: 'TX',
value: '64.8',
},
{
id: 'MN',
value: '41.2',
},
{
id: 'IA',
value: '47.8',
},
{
id: 'MO',
value: '54.5',
},
{
id: 'AR',
value: '60.4',
},
{
id: 'LA',
value: '66.4',
},
{
id: 'WI',
value: '43.1',
},
{
id: 'IL',
value: '51.8',
},
{
id: 'KY',
value: '55.6',
},
{
id: 'TN',
value: '57.6',
},
{
id: 'MS',
value: '63.4',
},
{
id: 'AL',
value: '62.8',
},
{
id: 'GA',
value: '63.5',
},
{
id: 'MI',
value: '44.4',
},
{
id: 'IN',
value: '51.7',
},
{
id: 'OH',
value: '50.7',
},
{
id: 'PA',
value: '48.8',
},
{
id: 'NY',
value: '45.4',
},
{
id: 'VT',
value: '42.9',
},
{
id: 'NH',
value: '43.8',
},
{
id: 'ME',
value: '41.0',
},
{
id: 'MA',
value: '47.9',
},
{
id: 'CT',
value: '49.0',
},
{
id: 'NJ',
value: '52.7',
},
{
id: 'WV',
value: '51.8',
},
{
id: 'VA',
value: '55.1',
},
{
id: 'NC',
value: '59.0',
},
{
id: 'SC',
value: '62.4',
},
{
id: 'FL',
value: '70.7',
},
];
// };
FusionCharts.ready(function () {
var chart = new FusionCharts({
type: 'maps/usa',
caption: 'Average Temperature of US States',
subcaption: '1979 - 2000',
entityfillhovercolor: '#F8F8E9',
numbersuffix: '°F',
showlabels: '1',
borderthickness: '0.4',
theme: 'fusion',
entitytooltext:
'<b>$lname</b> has an average temperature of <b>$datavalue</b>',
renderAt: 'chart-container',
width: '700',
height: '500',
colorrange: colorrange,
dataFormat: 'json',
dataSource: {
chart: {
caption: 'Average Temperature of US States',
subcaption: '1979 - 2000',
entityfillhovercolor: '#F8F8E9',
numbersuffix: '°F',
showlabels: '1',
borderthickness: '0.4',
theme: 'fusion',
entitytooltext:
'<b>$lname</b> has an average temperature of <b>$datavalue</b>',
// "animation":0,
// "defaultAnimation":0
},
colorrange: colorrange,
data: data,
},
events: {
preRender: function (event, data) {
// code to be executed before the chart is re-rendered
},
postRender: function (event, data) {
// code to be executed after the chart is re-rendered
},
entityRollover: function (event, data) {
console.log('test..' + data.label);
// Here we get a reference to the paragraph element and set its innerText to be the state's name we are hovering on
paragraphEl.current.innerText = data.label;
},
},
}).render();
});
return (
<Grid container spacing={2}>
<Grid item xs={9}>
<div id="chart-container"></div>
</Grid>
<Grid item xs={3}>
// we create a p element that will hold state's name on hover
<p ref={paragraphEl}></p>
{/* {hoveredState} */}
</Grid>
</Grid>
);
}
I'm trying to add a chart in a ReactJS page. In the same page I've got the data in a table and I would like that those data were the same of my chart. My chart is like this:
export const myDataSourcePie ={
chart: {
caption: "Title",
subcaption: "Friends' chart",
startingangle: "120",
showlabels: "0",
showlegend: "1",
enablemultislicing: "0",
slicingdistance: "15",
showpercentvalues: "1",
showpercentintooltip: "0",
plottooltext: "Friend's email : $label Total messages : $datavalue",
theme: "ocean"
},
data: [
{
label: 'email',
value: '17',
},
{
label: 'email',
value: '100',
},
{
label: 'email',
value: '17',
},
{
label: 'email',
value: '17',
},
{
label: 'email',
value: '17',
},
{
label: 'email',
value: '17',
},
{
label: 'email',
value: '100',
},
{
label: 'email',
value: '17',
},
]
}
export const chartConfigs = {
type: 'pie3d',
width: 800,
height: 600,
dataFormat: 'json',
dataSource: myDataSourcePie
};
and I import it and then render it with
<ReactFC {...chartConfigs} />
now obviously the data inside my JSON are not the right data. I've got a "friends" object list
friends:[
{"first_name": "name",
"surname": "surname",
"email": "foo#foo.com",
"date_of_birth": "1982-02-20",
"nationality": "Japan",
"messages": 5
},
{...},
{...},
..
]
from which I get the data to put in the table and I would like to get only two label of this object list to put in the chart (email and messages). How could I put this value inside my "myDataSourcePie"? With props?
Thank you
Try this:
getFriendsChart()
{
let dataChart = [];
this.state.friends.forEach( function( friend ) {
dataChart.push(
{
label: friend.email,
value: friend.messages,
}
);
});
let tempConfig = {...chartConfigs};
tempConfig.dataSource.data = dataChart;
return tempConfig;
}
I'm trying to filter a dropdown options using the rowEntity value.
$scope.data = [{
'id_a': 1,
'code': 1,
'line': 'Line 1 '
}, {
'id_a': 2,
'code': 2,
'line': 'Line 2'
}, {
'id_a': 3,
'code': 1,
'line': 'Line 3'
}, {
'id_a': 4,
'code': 3,
'line': 'Line 4'
}];
$scope.opts = [{
id: 1,
value: 'A',
code: 1
}, {
id: 2,
value: 'B',
code: 2
}, {
id: 3,
value: 'C',
code: 1
}, {
id: 4,
value: 'D',
code: 1
}, {
id: 5,
value: 'E',
code: 3
}, {
id: 6,
value: 'F',
code: 2
}];
$scope.columns = [{
field: 'line',
enableCellEdit: false,
enableFiltering: false
}, {
field: 'code',
enableCellEdit: false,
enableFiltering: false
}, {
field: 'value',
enableFiltering: false,
width: 500,
editableCellTemplate: 'ui-grid/dropdownEditor',
editDropdownIdLabel: 'id',
editDropdownValueLabel: 'value',
editDropdownOptionsArray: $scope.opts
}];
$scope.gridOptions = {
enableCellEditOnFocus: true,
enableFiltering: true,
onRegisterApi: function(gridApi) {
$scope.gridApi = gridApi;
},
columnDefs: $scope.columns
};
$scope.gridOptions.data = $scope.data;
What i'm trying to do is load an array in editDropdownOptionsArray and then dynamically filter this array using a value.
If i'm in 'Line 1' then can only appear the options that have the same 'code' value.
In this case 'Line 1' have the code '1' then the dropdowns options are 'A','C','D'
How can i do this? Using cellFilter?
Here is a plunker with the base code.
Hope this works out for you, and feel free to accept it it does:
Working Plnkr
Set your template:
editableCellTemplate: 'dropdown.html'
Add dropdown.html to your project:
<select ng-model="MODEL_COL_FIELD" ng-options="item as item.value for
item in col.colDef.editDropdownOptionsArray | filter : { code:
row.entity.code}"></select>
Test:
After the solution from KreepN i've made some upgrades in the code because i wasn't getting the value of the row when i choose one option.
I add ui-grid-edit-dropdown on select and that's solved the problem.
Updated Plnkr
Once again thank you KreepN for your solution.
<ui-select multiple ng-model="content.categories" theme="bootstrap"name="category" on-select="isCategorySelected()" >
<ui-select-match placeholder="Select Category">
{{ $item.label }}
</ui-select-match>
<ui-select-choices repeat="category.value as category in categories | filter: {label: $select.search}">
<div ng-bind-html="category.label | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
The shown is my html code
$scope.categories = [
{ label: 'Action', value: 'action' },
{ label: 'Adventure', value: 'adventure' },
{ label: 'Comedy', value: 'comedy' },
{ label: 'Crime', value: 'crime' },
{ label: 'Faction', value: 'faction' },
{ label: 'Fantasy', value: 'fantasy' },
{ label: 'Historical', value: 'historical' },
{ label: 'Horror', value: 'horror' },
{ label: 'Mystery', value: 'mystery' },
{ label: 'Paranoid', value: 'paranoid' },
{ label: 'Philosophical', value: 'philosophical' },
{ label: 'Political', value: 'political' },
{ label: 'Realistic', value: 'realistic' },
{ label: 'Romance', value: 'romance' },
{ label: 'Saga', value: 'saga' },
{ label: 'Satire', value: 'satire' },
{ label: 'Science fiction', value: 'sciencefiction' },
{ label: 'Slice of Life', value: 'sliceoflife' },
{ label: 'Speculative', value: 'speculative' },
{ label: 'Thriller', value: 'thriller' },
{ label: 'Urban', value: 'urban' }
];
This is my javascript code.
The above code works fine for selecting the defind items in the categories.
Now if I assign a value to ng-model of ui-select it isn't updatind the view as we select an item.
$scope.content.categories = [action];
the above code snippet should change the view,but its not.Please help me how to do this.
You should be getting action is not defined in the console. Just put quotes around it.
$scope.content.categories = ['action'];
var app = angular.module('app', ['ui.select', 'ngSanitize']);
app.controller('myController', function($scope) {
$scope.content = {};
$scope.content.categories = ['action'];
$scope.setAdventure = function() {
$scope.content.categories = ['adventure'];
};
$scope.pushComedy = function() {
if ($scope.content.categories.indexOf('comedy') === -1) {
$scope.content.categories.push('comedy');
}
};
$scope.categories = [{
label: 'Action',
value: 'action'
}, {
label: 'Adventure',
value: 'adventure'
}, {
label: 'Comedy',
value: 'comedy'
}, {
label: 'Crime',
value: 'crime'
}, {
label: 'Faction',
value: 'faction'
}, {
label: 'Fantasy',
value: 'fantasy'
}, {
label: 'Historical',
value: 'historical'
}, {
label: 'Horror',
value: 'horror'
}, {
label: 'Mystery',
value: 'mystery'
}, {
label: 'Paranoid',
value: 'paranoid'
}, {
label: 'Philosophical',
value: 'philosophical'
}, {
label: 'Political',
value: 'political'
}, {
label: 'Realistic',
value: 'realistic'
}, {
label: 'Romance',
value: 'romance'
}, {
label: 'Saga',
value: 'saga'
}, {
label: 'Satire',
value: 'satire'
}, {
label: 'Science fiction',
value: 'sciencefiction'
}, {
label: 'Slice of Life',
value: 'sliceoflife'
}, {
label: 'Speculative',
value: 'speculative'
}, {
label: 'Thriller',
value: 'thriller'
}, {
label: 'Urban',
value: 'urban'
}];
});
body {
padding: 15px;
}
.select2 > .select2-choice.ui-select-match {
/* Because of the inclusion of Bootstrap */
height: 29px;
}
.selectize-control > .selectize-dropdown {
top: 36px;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.3.15/angular-sanitize.js"></script>
<script type="text/javascript" src="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-select/0.12.0/select.js"></script>
<link rel="stylesheet" href="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.css">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/angular-ui-select/0.12.0/select.min.css">
<link rel="stylesheet" href="http://cdnjs.cloudflare.com/ajax/libs/selectize.js/0.8.5/css/selectize.default.css">
<div ng-app='app' ng-controller='myController'>
<button ng-click="setAdventure()">setAdventure</button>
<button ng-click="pushComedy()">pushComedy</button>
{{ content.categories }}
<ui-select multiple ng-model="content.categories" theme="bootstrap" name="category" on-select="isCategorySelected()" style="width: 300px;">
<ui-select-match placeholder="Select Category">
{{ $item.label }}
</ui-select-match>
<ui-select-choices repeat="category.value as category in categories | filter: {label: $select.search}">
<div ng-bind-html="category.label | highlight: $select.search"></div>
</ui-select-choices>
</ui-select>
</div>
I have a treeview like below, i need to remove one child from the list based on the user. Can any one tell me how to remove the child from the treeview.
var treedata = [
{
label: 'Floor', type: 'Country',
children: [
{
label: 'Bangalore', type: 'Location',
children: [{ label: 'Technopolis', type: 'facility', id: 1 }, { label: 'Ecity Tower-2', type: 'facility', id: 2 }, { label: 'Bagmane', type: 'facility', id: 3 }, { label: 'Cyber Park', type: 'facility', id: 4 }]
},
{
label: 'Hyderabad', type: 'Location',
children: [{ label: 'Hitech City ', type: 'facility', id: 5 }, { label: 'Cyber City', type: 'facility', id: 6 }]
},
{
label: 'Chennai', type: 'Location',
children: [{ label: 'XXX', type: 'facility', id: 7 }]
},
{
label: 'Mumbai', type: 'facility', id: 8
}
]
},
{
label: 'Role Administration', type: 'Role',
children: [{ label: 'Assign Role', type: 'Role', id: 1 }]
},
{
label: 'Hoteling Admin', type: 'Hoteling',
children: [{ label: 'Hoteling', type: 'Hoteling', id: 1 }]
}
];
The above is my jquery tree data. I want to remove the role administration if the user is a normal user by checking the user role.
Anyone help me how to do using jquery.
Thanks
You can use $.grep() to filter the array to a new array based on whatever conditions you want.
var userRole='normal';
if( userRole === 'normal'){
treeview = $.grep(treeview, function(item){
return item.label != 'Role Administration';
});
}
grep() API docs