2

I have a dynamic json object which contains a button element. I am using createElement and material UI to render the object data.

I wanted to apply customizable CSS using className in the button component, but I couldn't achieve it. So, how can I apply CSS in runtime to the material UI component?

Here is my code snippet:

import React, { useState } from "react";
import './App.css';
import { Button, Grid, Checkbox, TextField, Switch, Link } from '@mui/material';



const KeysToComponentMap = {
    button: Button,
    grid: Grid,
    checbox: Checkbox,
    text: TextField,
    switch: Switch,
    link: Link
};


const RenderCard = (props) => {



    const SampleData =
        [
            {
                "type": "button",
                "display": "RELEASE THE BATCH",
                "key": "RS",
                "class": "btn",
                "value": [
                    {
                        "type": "button",
                        "display": "CONFIRM AND SUBMIT",
                        "key": "key1",
                        "value": "post"
                    }
                ]
            },
            {
                "type": "button",
                "display": "RELEASE THE OBSERVATION",
                "key": "RO",
                "value": [
                    {
                        "type": "input",
                        "display": "Observation",
                        "key": "key8",
                        "value": "val1"
                    },
                    {
                        "type": "button",
                        "display": "Done",
                        "key": "key9",
                        "value": [
                            {
                                "type": "button",
                                "display": "CONFIRM AND SUBMIT",
                                "key": "key10",
                                "value": "post"
                            }
                        ]
                    }
                ]
            }
        ]

    }




    return (
        <>{

            
                {SampleData.map((item, index) => {
                    console.log(item.type);
                    console.log(item.class)
                    
                    if (typeof KeysToComponentMap[item.type] !== "undefined") {
                        
                        return (
                            React.createElement(
                                KeysToComponentMap[item.type],
                                {
                                    onClick: () => { onButtonHandler(item, item.key) },
                                    variant: "contained",
                                    type: "input",
                                    className: KeysToComponentMap[item.class],
                                    
                                },
                                
                                item.display &&
                                (typeof item.display === "string"
                                ? item.display
                                : item.value.map(c => ActivityDetail(c)))
                            ))
                            
                    }
                    
                })} 
                
        }
            
        </>)
}

export default RenderCard;
2
  • What exactly is not working ? Maybe the problem is that none of the objects in SampleData have a class property Commented Feb 10, 2022 at 13:21
  • @Titus, That's what I wanted to know, what is a correct way to give className property in the json object so that it will apply style to button element and then access it inside the React createElement Commented Feb 10, 2022 at 13:39

1 Answer 1

1

Original Question:

Your problem isn't that the className isn't being applied, it's that the value that you're trying to assign from KeysToComponentMap (KeysToComponentMap[item.class]) is returning undefined. I had to modify your code, and add a class property to your Sample JSON, to get it to work so you may want to change it however you need it:

{
  onClick: () => {
    onButtonHandler(item, item.key);
  },
  variant: "contained",
  type: "input",
  className: item.class // Changed from `className: KeysToComponentMap[item.class]`
},

Working Code Sandbox: https://codesandbox.io/s/classname-cjlqo?file=/demo.js

Question from Comments:

in case if i want to pass style directly instead of classname then in what format should be style property be in sample JSON. I was passing style in json like: [{"style": "color: 'red'"}] but it is a wrong way that's why not working. So, what is the correct way?

Since you are using MUI 5, the correct prop to pass inline styles is sx. You may want to make your configuration a bit more flexible by just passing whatever additional properties each component might need straight through and spreading them into the component directly. For example:

// Sample config:
{
  type: "button",
  display: "RELEASE THE BATCH",
  key: "RS",
  className: "my-button",
  sx: { color: "blue" },
  value: [
    {
      type: "button",
      display: "CONFIRM AND SUBMIT",
      key: "key1",
      value: "post"
    }
  ]
},


// Renderer
    <>
      {SampleData.map(({ type, key, display, value, ...rest }, index) => {
        console.log(type);

        if (typeof KeysToComponentMap[type] !== "undefined") {
          return React.createElement(
            KeysToComponentMap[type],
            {
              onClick: () => {
                onButtonHandler(item, key);
              },
              variant: "contained",
              type: "input",
              ...rest
            },

            display &&
              (typeof display === "string"
                ? display
                : value.map((c) => ActivityDetail(c)))
          );
        }
      })}
    </>

Working example with className and style: https://codesandbox.io/s/style-e4inc?file=/demo.js

Sign up to request clarification or add additional context in comments.

2 Comments

I tried with ur solution and it worked for me. I have one more question i.e. in case if i want to pass style directly instead of classname then in what format should be style property be in sample JSON. I was passing style in json like: [{"style": "color: 'red'"}] but it is a wrong way that's why not working. So, what is the correct way?
@VK7 I've updated my answer to accommodate your follow-up question.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.