react-grid layout html not updating cols - reactjs

I use react Grid-layout : https://github.com/react-grid-layout/react-grid-layout
I do not understand why the number of column does not update in my table through the web browser.
In fact, this.props.cols.lg is either 17 or 24.
When it's 17, my table is displayed correctly. On the other hand, when I choose a period with 24 columns, my columns are placed one below the other from the 18th.
this.props.cols.lg to the correct value (17 or 24) but my HTML page does not update to the design level.
This is the right table on one single row :
Right table
Like you can see, the firefox web console shows react properties are good with 17 :
and the bad table
Bad table
here again, the firefox web console shows react properties are right (24) but not applied by the web browser :
Important information,
this.props.cols.lg=loopValue+1; **contains the right value (17 or 24) but apply on 17**
Thank you in advance for your help.
Here is a part of my code:
import React, { useState, useEffect, Fragment } from 'react';
import { WidthProvider, Responsive } from "react-grid-layout";
import ReactTooltip from 'react-tooltip';
import _ from "lodash";
import { Button, Container } from 'react-bootstrap';
const ResponsiveReactGridLayout = WidthProvider(Responsive);
import { Responsive as ResponsiveGridLayout } from 'react-grid-layout';
/**
* This layout demonstrates how to use a grid with a dynamic number of elements.
*/
export class AddRemoveLayout extends React.PureComponent {
//les propriétés par défaut
static defaultProps = {
className: "layout border-darken-1 child-background-color",
cols:
{ lg: 10, md: 10, sm: 10, xs: 10, xxs: 10 },
width: 1000,
margin: [0, 0],
preventCollision: true,
autoSize: true,
// preventCollision: true,
rowHeight: 70,
// Build HTML to insert
render() {
//Week
let createDateItem =
(x, y, day) => ({
i: `date-${x}_${y}`,
x,
y,
w: 1,
h: 1,
myText: `${day}` ,
static: true
});
/**
*
* #param {*} y
* #param {*} xStart
* #param {num semaine} dateStart
* #param {nombre semaine total} count
*/
let getDateItems =
(y, xStart, dateStart, count,dateEnd) => {
let items = [];
let loopValue = 0;
while(dateStart<=dateEnd){//semainee
if(loopValue>1){
dateStart.setDate(dateStart.getDate() + 7)
}
if(dateStart<=dateEnd){
items.push(
createDateItem(xStart + loopValue, y, loopValue === 0 ? 0 :
(dateStart.getDate()+"/" +(dateStart.getUTCMonth()+1)+ " (Sem. "+loopValue +") ")
))
}
loopValue++;
}
console.log('props:')
console.log(this.props);
this.props.cols.lg=loopValue+1;
this.props.cols.md=loopValue+1;
this.props.cols.sm=loopValue+1;
this.props.cols.xs=loopValue+1;
this.props.cols.xxsloopValue+1;
console.log(this.props);
// console.log(AddRemoveLayout.defaultProps)
return items;
}
;

We found the solution :
data: { idHoraire: 1 },
It was always the same item sent to PHP, with this code, I have a great dispaly of my cols because I either send 1 (17 cols) or 2 (25 cols) :
data: { idHoraire: url === "index2" ?2 : 1, },

Related

how to show speedometer on Doughnut chart in chart.js using reactjs

I've created a half doughnut chart and wanted to show like a speedometer, but couldn't able to make it. I have gone through this link I want to display my chart Either as similar to the above link or as per this snippet
Here is my code:
import React, { Component } from "react";
import { Doughnut } from "react-chartjs-2";
import Data from "./Data.json";
const data = {
// labels: ["Red", "Green", "Yellow"],
datasets: [
{
data: [500, 500, 500],
backgroundColor: ["red", "#FFCE56", "lightgreen"],
hoverBackgroundColor: ["red", "#FFCE56", "lightgreen"]
}
],
options: {
rotation: 1 * Math.PI,
circumference: 1 * Math.PI,
legend: {
display: false
},
tooltip: {
enabled: false
},
cutoutPercentage: 70
}
};
export default class DonutChart extends Component {
render() {
return (
<div>
<h2>Sample</h2>
<Doughnut height="100px" data={data} options={data.options} />
</div>
);
}
}
Here is the sample code
Can anyone help me in this query to achieve in this format?
Base on the code sample from Konstantin S., you could register a plugin globally inside the componentDidMount() method and implement an afterDraw function as follows:
componentDidMount() {
Chart.pluginService.register({
afterDraw: chart => {
var needleValue = chart.chart.config.data.datasets[0].needleValue;
var dataTotal = chart.chart.config.data.datasets[0].data.reduce((a, b) => a + b, 0);
var angle = Math.PI + (1 / dataTotal * needleValue * Math.PI);
var ctx = chart.chart.ctx;
var cw = chart.chart.canvas.offsetWidth;
var ch = chart.chart.canvas.offsetHeight;
var cx = cw / 2;
var cy = ch - 6;
ctx.translate(cx, cy);
ctx.rotate(angle);
ctx.beginPath();
ctx.moveTo(0, -3);
ctx.lineTo(ch - 10, 0);
ctx.lineTo(0, 3);
ctx.fillStyle = 'rgb(0, 0, 0)';
ctx.fill();
ctx.rotate(-angle);
ctx.translate(-cx, -cy);
ctx.beginPath();
ctx.arc(cx, cy, 5, 0, Math.PI * 2);
ctx.fill();
}
});
}
This expects the property needleValue to be defined inside the dataset.
datasets: [{
data: [500, 500, 500],
needleValue: 580,
...
}],
Please have a look at your amended CodeSandbox

Prevent JointJS elements from generating off paper

I'm using JointJS in a React environment to create a Directed graph from some Neo4j data. My problem is that elements are being generated off the paper As pictured here, "test6" is generated mostly off the page and "test10" isn't even shown. I would like all elements to be displayed on the paper, without overlapping each other or links if possible.
My paper is defined with only a width dimension set equal to the div width and the div is styled to be 100% width
...
width: $('#paper').width(),
...
and
render(){
return(
<React.Fragment>
<div id="paper" style={{width:'100%'}}></div>
</React.Fragment>
)
}
The code for generating an element is as follows:
function makeElement(node) {
var maxLineLength = _.max(node.name.split('\n'), function(l) { return l.length; }).length;
var letterSize = 12;
var width = 2 * (letterSize * (0.6 * maxLineLength + 1));
var height = 2 * ((node.name.split('\n').length + 1) * letterSize);
return new joint.shapes.basic.Rect({
id: node.id,
size: { width: 100, height: height },
attrs: {
type:'node',
text: {
text: node.name,
'font-size': letterSize,
'font-family': 'monospace' },
rect: {
width: width, height: height,
rx: 5, ry: 5,
stroke: '#555'
}
}
});
}
Thanks in advance :)
EDIT: I don't have the exact solution yet, but in the meantime I used this to make the paper draggable to view all nodes

Load SVG div to React component

I'm using an NPM package that draws a fretboard using D3 (https://github.com/txels/fretboard) .It outputs a div with SVG. I have it working with a normal HTML page but if I try and load it to a React component with code below it gets appended to end of page rather than in div where I have the expression.
Any ideas how I get this generated div in the component div?
import React from "react";
import { Fretboard, Tunings } from "fretboards";
const GenerateFret = () => {
const config = {
frets: 12, // Number of frets to display
startFret: 0, // Initial fret
strings: 6, // Strings
tuning: Tunings.guitar6.standard, // Tuning: default = Standard Guitar
fretWidth: 50, // Display width of frets in pixels
fretHeight: 20, // Display heigh of frets in pixels
leftHanded: false, // Show mirror image for left handed players
showTitle: true, // Set the note name as the title, so it will display on hover
where="#fret"
};
const notes =
"6:e2 6:f2 6:f#2 6:g2 6:g#2 6:a2 6:a#2 6:b2 6:c3 6:c#3 6:d3 6:d#3 6:e3 " +
"5:a2 5:a#2 5:b2 5:c3 5:c#3 5:d3 5:d#3 5:e3 5:f3 5:f#3 5:g3 5:g#3 5:a3 " +
"4:d3 4:d#3 4:e3 4:f3 4:f#3 4:g3 4:g#3 4:a3 4:a#3 4:b3 4:c4 4:c#4 4:d4 " +
"3:g3 3:g#3 3:a3 3:a#3 3:b3 3:c4 3:c#4 3:d4 3:d#4 3:e4 3:f4 3:f#4 3:g4 " +
"2:b3 2:c4 2:c#4 2:d4 2:d#4 2:e4 2:f4 2:f#4 2:g4 2:g#4 2:a4 2:a#4 2:b4 " +
"1:e4 1:f4 1:f#4 1:g4 1:g#4 1:a4 1:a#4 1:b4 1:c5 1:c#5 1:d5 1:d#5 1:e5";
let board = Fretboard(config);
board.draw(notes);
};
const GameArea = () => {
return (
<div id="fret" className="col-8 border border-primary fb-container">
{GenerateFret()}
</div>
);
};
export default GameArea;
There is a config for [where] which changes the D3 selection from body.
I tried adding an ID to the div and then passing in where="#fret" to the config const but this stops any visual from being output.
Manually changing the DOM in React components is an example of side effect and therefore should be put inside useEffect
Try:
const GameArea = () => {
useEffect(()=>{
GenerateFret(); // call function inside useEffect
}, []) // you need to run it only once, so pass empty array
return (
<div id="fret" className="col-8 border border-primary fb-container"/>
);
};
This is the whole code:
import React from "react";
import { Fretboard, Tunings } from "fretboards";
const GenerateFret = () => {
const config = {
frets: 12, // Number of frets to display
startFret: 0, // Initial fret
strings: 6, // Strings
tuning: Tunings.guitar6.standard, // Tuning: default = Standard Guitar
fretWidth: 50, // Display width of frets in pixels
fretHeight: 20, // Display heigh of frets in pixels
leftHanded: false, // Show mirror image for left handed players
showTitle: true, // Set the note name as the title, so it will display on hover
where="#fret"
};
const notes =
"6:e2 6:f2 6:f#2 6:g2 6:g#2 6:a2 6:a#2 6:b2 6:c3 6:c#3 6:d3 6:d#3 6:e3 " +
"5:a2 5:a#2 5:b2 5:c3 5:c#3 5:d3 5:d#3 5:e3 5:f3 5:f#3 5:g3 5:g#3 5:a3 " +
"4:d3 4:d#3 4:e3 4:f3 4:f#3 4:g3 4:g#3 4:a3 4:a#3 4:b3 4:c4 4:c#4 4:d4 " +
"3:g3 3:g#3 3:a3 3:a#3 3:b3 3:c4 3:c#4 3:d4 3:d#4 3:e4 3:f4 3:f#4 3:g4 " +
"2:b3 2:c4 2:c#4 2:d4 2:d#4 2:e4 2:f4 2:f#4 2:g4 2:g#4 2:a4 2:a#4 2:b4 " +
"1:e4 1:f4 1:f#4 1:g4 1:g#4 1:a4 1:a#4 1:b4 1:c5 1:c#5 1:d5 1:d#5 1:e5";
let board = Fretboard(config);
board.draw(notes);
};
const GameArea = () => {
useEffect(()=>{
GenerateFret(); // call function inside useEffect
}, []) // you need to run it only once, so pass empty array
return (
<div id="fret" className="col-8 border border-primary fb-container"/>
);
};

How to create and set a setMapTypeId using react-google-maps

I was looking for a way to create my own mars map in a website, using google maps.
I found this example in google map api
function initMap() {
var map = new google.maps.Map(document.getElementById('map'), {
center: {lat: 0, lng: 0},
zoom: 1,
streetViewControl: false,
mapTypeControlOptions: {
mapTypeIds: ['moon']
}
});
var moonMapType = new google.maps.ImageMapType({
getTileUrl: function(coord, zoom) {
var normalizedCoord = getNormalizedCoord(coord, zoom);
if (!normalizedCoord) {
return null;
}
var bound = Math.pow(2, zoom);
return '//mw1.google.com/mw-planetary/lunar/lunarmaps_v1/clem_bw' +
'/' + zoom + '/' + normalizedCoord.x + '/' +
(bound - normalizedCoord.y - 1) + '.jpg';
},
tileSize: new google.maps.Size(256, 256),
maxZoom: 9,
minZoom: 0,
radius: 1738000,
name: 'Moon'
});
map.mapTypes.set('moon', moonMapType);
map.setMapTypeId('moon');
}
// Normalizes the coords that tiles repeat across the x axis (horizontally)
// like the standard Google map tiles.
function getNormalizedCoord(coord, zoom) {
var y = coord.y;
var x = coord.x;
// tile range in one direction range is dependent on zoom level
// 0 = 1 tile, 1 = 2 tiles, 2 = 4 tiles, 3 = 8 tiles, etc
var tileRange = 1 << zoom;
// don't repeat across y-axis (vertically)
if (y < 0 || y >= tileRange) {
return null;
}
// repeat across x-axis
if (x < 0 || x >= tileRange) {
x = (x % tileRange + tileRange) % tileRange;
}
return {x: x, y: y};
}
/* Always set the map height explicitly to define the size of the div
* element that contains the map. */
#map {
height: 100%;
}
/* Optional: Makes the sample page fill the window. */
html, body {
height: 100%;
margin: 0;
padding: 0;
}
<div id="map"></div>
<!-- Replace the value of the key parameter with your own API key. -->
<script
async
defer
src="https://maps.googleapis.com/maps/api/js?key=AIzaSyCkUOdZ5y7hMm0yrcCQoCvLwzdM6M8s5qk&callback=initMap">
</script>
https://jsfiddle.net/dobleuber/319kgLh4/
It works perfect, but I would like to create the same thing with react using react-google-maps.
I looked out in the react-google-maps code but I only see getters no setters for the map props:
getMapTypeId, getStreetView, ect.
Is there any way to achieve this without modify the react-google-maps code?
Thanks in advance
use props mapTypeId="moon" in react-google-maps
I've found a better way to solve this that preserve the changes on re-render, leaving it here to anyone who comes here.
there is an onLoad function that exposes a map instance, we can use this to set mapTypeId instead of passing it as an option. In this way, if the user changes the map type later, it will preserve the changes on re-render.
<GoogleMap
onLoad={(map) => {
map.setMapTypeId('moon');
}}
/>

Combining react-leaflet and leaflet-pixi-overlay

I am trying to display a complex map with many moving markers, with different icons etc... I have a pure react / react-leaflet solution, but it start to struggle with ~1k markers moving every second.
It looks like leaflet-pixi-overlay could be a way of really speeding things up. But I am just starting with the whole chain (react/javascript/maps/leaflet/etc..) and have problems when connecting all this.
Right now I am just trying to display a polygon in my overlay, and nothing is rendered. It turns out that the translation of lat/long to x/y is failing for that polygon's points. Pixi's latLngToLayerPoint function returns 'infinity' for x and y.
This seems to come from the fact that the zoom is not defined for the layer in question (it is 'infinity' also).
Even if I call latLngToLayerPoint with the zoom setting from the map, things fail too (x/y values are not infinite any more, but they are way out there).
This is my code:
import React, { useEffect, useRef } from 'react';
import { Map, TileLayer } from 'react-leaflet'
import "leaflet/dist/leaflet.css"
import * as PIXI from 'pixi.js'
import 'leaflet-pixi-overlay' // Must be called before the 'leaflet' import
import L from 'leaflet';
let polyLatLngs = [[50.630, 13.047], [50.645, 13.070], [50.625, 13.090], [50.608, 13.070], [50.630, 13.047]]
let pixiContainer = new PIXI.Container()
let prevZoom
let firstDraw = true;
let projectedPolygon;
var shape = new PIXI.Graphics();
pixiContainer.addChild(shape);
let myOverlay = L.pixiOverlay(function (utils) {
let map = utils.getMap()
let zoom = map.getZoom()
console.log('map zoom=' + zoom + ', center=' + map.getCenter())
console.log(' bounds=' + JSON.stringify(map.getBounds()))
console.log(' size=' + map.getSize() + ', panes=' + JSON.stringify(map.getPanes()))
if (map) {
var container = utils.getContainer();
var renderer = utils.getRenderer();
var project = utils.latLngToLayerPoint;
var scale = utils.getScale();
if (firstDraw) {
projectedPolygon = polyLatLngs.map((coords, index) => {
console.log('i=' + index + ', coords=' + coords + ', proj=' + project(coords))
return project(coords)
// return project(coords, zoom) // : this fails too
})
}
if (firstDraw || prevZoom !== zoom) {
shape.clear();
shape.lineStyle(3 / scale, 0x3388ff, 1);
shape.beginFill(0x3388ff, 0.2);
projectedPolygon.forEach(function (coords, index) {
if (index === 0) shape.moveTo(coords.x, coords.y);
else shape.lineTo(coords.x, coords.y);
});
shape.endFill();
}
firstDraw = false;
prevZoom = zoom;
renderer.render(container);
}
}, pixiContainer)
function PxMap(props) {
const mapRef = useRef(null);
useEffect(() => {
if (mapRef.current !== null) {
let map = mapRef.current.leafletElement;
console.log('useEffect: add overlay ')
console.log(JSON.stringify(map.getPane('overlayPane').childElementCount))
myOverlay.addTo(map);
console.log(JSON.stringify(map.getPane('overlayPane').childElementCount))
}
}, [mapRef]);
return (
<div style={{ flexgrow: 1, height: '100%' }}>
<Map
preferCanvas={true}
ref={mapRef}
style={{ height: '100%' }}
center={[50.63, 13.047]}
zoom={12}
>
<TileLayer
attribution='&copy OpenStreetMap contributors'
url="https://{s}.tile.openstreetmap.org/{z}/{x}/{y}.png?"
/>
</Map>
</div>
)
}
export default PxMap
I think that things are connected correctly between React and leaflet, the map displays ok, I can see the overlay being added etc...
BUT there is a connection missing somewhere, to give more context / information to PIXI.
Any ideas? Thanks!
Finally found the problem, drilling down into the leaflet-pixi-overlay lib.
The solution is to define the minZoom and maxZoom in the Map element:
<Map
preferCanvas={true}
ref={mapRef}
style={{ height: '100%' }}
center={[50.63, 13.047]}
zoom={12}
minZoom={ 9} // Add these options...
maxZoom={ 16} //
Internally, L.PixiOverlay.js relies on these two values to define:
// return the layer projection zoom level
projectionZoom: function (map) {return (map.getMaxZoom() + map.getMinZoom()) / 2;},
Which in turn is used to define the default zoom setting?
this._initialZoom = this.options.projectionZoom(map);
....
zoom = (zoom === undefined) ? _layer._initialZoom : zoom;
var projectedPoint = map.project(L.latLng(latLng), zoom);
Not sure why this is done this way, but setting these options solves the problem.

Resources