Cover image for mayankprasoon

mayankprasoon

App builder

mayankprasoon

How to Pass Dynamic Variables to Custom Widgets in Appsmith?

December 21, 2024
0
ยท 0

Like mentioned earlier. This is the custom widget code:

```
import React, { useEffect, useRef, useState } from 'https://cdn.jsdelivr.net/npm/react@18.2.0/+esm'
import reactDom from 'https://cdn.jsdelivr.net/npm/react-dom@18.2.0/+esm'
import { Button, Card } from 'https://cdn.jsdelivr.net/npm/antd@5.11.1/+esm'
import Markdown from 'https://cdn.jsdelivr.net/npm/react-markdown@9.0.1/+esm';
import * as d3 from 'https://cdn.jsdelivr.net/npm/d3@7.9.0/+esm';

const BubbleMap = () => {
 const [indiaGeoData, setIndiaGeoData] = useState(null);
 
 // Fixed dimensions
 const width = 740;
 const height = 800;

 // Sample data for Indian cities
 const cities = appsmith.model.dataPins;

 useEffect(() => {
   // Fetch India GeoJSON data
   fetch(appsmith.model.geoMap)
     .then(response => response.json())
     .then(data => {
       setIndiaGeoData(data);
     })
     .catch(error => console.error('Error loading map data:', error));
 }, []);

 // Create the projection
 const projection = d3.geoMercator()
   .center(appsmith.model.geoMapCenter) // Adjusted center for India
   .scale(1200)
   .translate([width / 2, height / 2]);

 // Create path generator
 const pathGenerator = d3.geoPath().projection(projection);

 // Create scales
 const maxValue = 100;
 const sizeScale = d3.scaleSqrt()
   .domain([0, maxValue])
   .range([5, 10]);

 const colorScale = d3.scaleSequential().range([" #ff0000 ", "#00ff00"])
   .domain([0, maxValue]);

 // Project coordinates
 const projectedCities = cities.map(city => {
   const position = projection([city.lon, city.lat]);
   return {
     ...city,
     x: position[0],
     y: position[1]
   };
 });

 return (
   <div style={{ border: '1px solid #ccc', margin: '20px', padding: '10px' }}>
     <svg width={width} height={height} style={{ background: '#f0f0f0' }}>
       {/* Background */}
       <rect width={width} height={height} fill="#f8fafc" />
       
       {/* India Map */}
       {indiaGeoData && (
         <g className="states">
           {indiaGeoData.features.map((feature, i) => (
             <path
               key={i}
               d={pathGenerator(feature)}
               fill="#e5e7eb"
               stroke="#cbd5e1"
               strokeWidth={0.5}
             />
           ))}
         </g>
       )}
       
       {/* Cities */}
       {projectedCities.map((city, i) => (
         <g key={i}>
           {/* Bubble */}
           <circle
             cx={city.x}
             cy={city.y}
             r={sizeScale(city.value)}
             fill={colorScale(city.value)}
             opacity={0.7}
             stroke="#fff"
             strokeWidth={1}
           />
           
           {/* City name */}
           <text
             x={city.x}
             y={city.y - sizeScale(city.value) - 5}
             textAnchor="middle"
             fontSize="12px"
             fill="#333"
             fontWeight="bold"
           >
             {city.name}
           </text>
           
           {/* Value */}
           <text
             x={city.x}
             y={city.y + sizeScale(city.value) + 15}
             textAnchor="middle"
             fontSize="10px"
             fill="#666"
           >
             {city.value}%
           </text>
         </g>
       ))}

       {/* Legend */}
       <g transform={`translate(${width - 100}, ${height - 120})`}>
         <text y={-10} fontSize="12px" fill="#333" fontWeight="bold">
           Availability (%)
         </text>
         {[0, 25, 50, 75, 100].map((value, i) => (
           <g key={i} transform={`translate(0,${i * 25})`}>
             <circle
               r={sizeScale(value)}
               fill={colorScale(value)}
               opacity={0.7}
               stroke="#fff"
               strokeWidth={1}
             />
             <text x={35} y={5} fontSize="10px" fill="#666">
               {value}%
             </text>
           </g>
         ))}
       </g>
     </svg>
   </div>
 );
};

 

function App() {
    const [currentIndex, setCurrentIndex] = React.useState(0);

    const handleNext = () => {
        setCurrentIndex((prevIndex) => (prevIndex + 1) % appsmith.model.tips.length);
    };

    const handleReset = () => {
        setCurrentIndex(0);
        appsmith.triggerEvent("onResetClick");
    };
    console.log(1)

    return (
        <Card className="app">
            <BubbleMap />
    </Card>
);
}

appsmith.onReady(() => {
    /*
     * This handler function will get called when parent application is ready.
     * Initialize your component here
     * more info - https://docs.appsmith.com/reference/widgets/custom#onready
     */
    reactDom.render(<App />, document.getElementById("root"));
});
```

Now, in the above case, I have external query which fetch the data for the data pins to be shown to the users. The variable name being dataPins. So, whenever the required filters are selected, the query is run and I want to the data to pass into the graph to plot it accordingly.

 

I couldn't find any way to do this in the custom widget. Can someone please help? Or should I use a different way to do this?