Set custom SVG icon on Ag-Grid sidebar

Viewed 1113

I need to specify custom icons on my Ag-Grid (React) sidebar for custom panels. My toolpanels looks like this:

toolPanels: [
    {
        id: "actions",
        labelDefault: "Actions",
        labelKey: "actions",
        iconKey: "entityActions",                  
        toolPanel: "blotterActionsPanel",
        toolPanelParams: {glEventHub: this.props.glEventHub}
    },
    {
        id: "columns",
        labelDefault: "Columns",
        labelKey: "columns",
        iconKey: "columns",
        toolPanel: "agColumnsToolPanel"
    },
    {
        id: "filters",
        labelDefault: "Filters",
        labelKey: "filters",
        iconKey: "filter",
        toolPanel: "agFiltersToolPanel"
    }
]

for the 'actions' toolpanel I have iconKey 'entityActions', so my icons looks like this:

icons: {
    entityActions: '<i class="fa fa-running" style="font-size: 12pt; color: darkgrey"/>',
}

That works for a font-awesome icon... but I don't want to use an FA icon. I need to use icons from BlueprintJS, which are SVG icons. BlueprintJS provides an tag which would be the easiest to use... but I've tried various things like this:

icons: {
    entityActions: "<Icon icon='add'/>"
}

Which doesn't work... I can also get the raw SVG paths from BlueprintJS so I've tried:

entityActions: '<span><svg fill="black" height="16" width="16"  viewBox={"0 0 16 16"}><path d=' + IconSvgPaths16.add[0] + '/></svg></span>',

and also I tried hard-coding the path... In all of these cases I just get a blank hole where I expect the icon to be. The Ag-Grid documentation (https://www.ag-grid.com/javascript-grid-icons/):

The icon can be any of the following: String: The string will be treated as html. Use to return just text, or HTML tags. Function: A function that returns either a String or a DOM node or element.

so, I tried a function... I cannot find an example of how to do this, but after a few hours of searching I came across examples that show it creating an element using document.createElement.. So I tried this:

entityActions: params => {
    let icon = document.createElement('svg');
    let path = document.createElement('path');
    icon.setAttribute('fill', "black");
    icon.setAttribute("height", "16");
    icon.setAttribute("width", "16");
    icon.setAttribute("viewBox", "0 0 16 16");
    path.setAttribute("d", IconSvgPaths16.add[0]);                    
    icon.appendChild(path);
    return icon;
}

Still with no luck... How can I use a BlueprintJS Icon with Ag-Grid? This icon is actually customizable by the user so it would be good if I could use a function and pass in the icon name to use and have it return the appropriate one...

Thankyou, Troy.

2 Answers

I had similar requirements in my project too. This is how I solved it and hope it helps:

As The icon can be any of the following: String: The string will be treated as html. Use to return just text, or HTML tags. Function: A function that returns either a String or a DOM node or element.

So we can provide a function which will return a dom node. In the dom node, we can render a React component onto it.

e.g. You may render a MaterialUI Icon, or a Custom SVG Icon onto a dom node and then return it.

icons: {
    entityActions: () => {
        let domNode = document.createElement('div');
        ReactDOM.render(<YourOwnSVGIcon style={{color: 'yourColorCode'}}/>, domNode );
        return domNode ;
    }
}

Why not convert the BlueprintJS icon to a base64 string, and use that in a div with the base64 string as the background-image?

So your entityActions will look like this for the add icon:

`entityActions: `<div id="test" style='height: 20px; width: 20px; background-image: url("data:image/svg+xml;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0idXRmLTgiPz4KPCEtLSBHZW5lcmF0b3I6IEFkb2JlIElsbHVzdHJhdG9yIDE3LjEuMCwgU1ZHIEV4cG9ydCBQbHVnLUluIC4gU1ZHIFZlcnNpb246IDYuMDAgQnVpbGQgMCkgIC0tPgo8IURPQ1RZUEUgc3ZnIFBVQkxJQyAiLS8vVzNDLy9EVEQgU1ZHIDEuMS8vRU4iICJodHRwOi8vd3d3LnczLm9yZy9HcmFwaGljcy9TVkcvMS4xL0RURC9zdmcxMS5kdGQiPgo8c3ZnIHZlcnNpb249IjEuMSIgaWQ9IkxheWVyXzEiIHhtbG5zPSJodHRwOi8vd3d3LnczLm9yZy8yMDAwL3N2ZyIgeG1sbnM6eGxpbms9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkveGxpbmsiIHg9IjBweCIgeT0iMHB4IgoJIHZpZXdCb3g9IjAgMCAxNiAxNiIgZW5hYmxlLWJhY2tncm91bmQ9Im5ldyAwIDAgMTYgMTYiIHhtbDpzcGFjZT0icHJlc2VydmUiPgo8ZyBpZD0iYWRkXzNfIj4KCTxnPgoJCTxwYXRoIGZpbGwtcnVsZT0iZXZlbm9kZCIgY2xpcC1ydWxlPSJldmVub2RkIiBkPSJNMTAuOTksNi45OWgtMnYtMmMwLTAuNTUtMC40NS0xLTEtMXMtMSwwLjQ1LTEsMXYyaC0yYy0wLjU1LDAtMSwwLjQ1LTEsMQoJCQlzMC40NSwxLDEsMWgydjJjMCwwLjU1LDAuNDUsMSwxLDFzMS0wLjQ1LDEtMXYtMmgyYzAuNTUsMCwxLTAuNDUsMS0xUzExLjU0LDYuOTksMTAuOTksNi45OXogTTcuOTktMC4wMWMtNC40MiwwLTgsMy41OC04LDgKCQkJczMuNTgsOCw4LDhzOC0zLjU4LDgtOFMxMi40MS0wLjAxLDcuOTktMC4wMXogTTcuOTksMTMuOTljLTMuMzEsMC02LTIuNjktNi02czIuNjktNiw2LTZzNiwyLjY5LDYsNlMxMS4zMSwxMy45OSw3Ljk5LDEzLjk5eiIvPgoJPC9nPgo8L2c+Cjwvc3ZnPgo")'>`

Here's a StackBlitz of this working.

Related