Generate Material Timeline from JSON Object

Viewed 257

I have this Json object generated by BE:

{
  "step1": {
    "approved": true,
    "approvalTime": "10-11-2021",
    "title": "title 1",
    "description": "description 1"
  },
  "step2": {
    "approved": true,
    "approvalTime": "10-11-2021",
    "title": "title 2",
    "description": "description 2"
  },
  "step3": {
    "approved": true,
    "approvalTime": "10-11-2021",
    "title": "title 3",
    "description": "description 3"
  }
}

Material Timeline:

                     <Timeline align="alternate">
                        <TimelineItem>
                            <TimelineOppositeContent>
                                <Typography variant="body2" color="textSecondary"> // get color form Json
                                    9:30 am  // get this value from JSON
                                </Typography>
                            </TimelineOppositeContent>
                            <TimelineSeparator>
                                <TimelineDot>
                                    <LibraryBooks />
                                </TimelineDot>
                                <TimelineConnector />
                            </TimelineSeparator>
                            <TimelineContent>
                                <Paper elevation={3} className={classesTimeline.paper}>
                                    <Typography variant="h6" component="h1">
                                        title 1 // get title from JSON
                                    </Typography>
                                    <Typography> // get description from JSON</Typography>
                                </Paper>
                            </TimelineContent>
                        </TimelineItem>

                        <TimelineItem>
                            <TimelineOppositeContent>
                                <Typography variant="body2" color="textSecondary">
                                    11:00 am // get this value from JSON
                                </Typography>
                            </TimelineOppositeContent>
                            <TimelineSeparator>
                                <TimelineDot color="primary">
                                    <PeopleAlt />
                                </TimelineDot>
                                <TimelineConnector />
                            </TimelineSeparator>
                            <TimelineContent>
                                <Paper elevation={3} className={classesTimeline.paper}>
                                    <Typography variant="h6" component="h1">
                                        title 2 // get title from JSON
                                    </Typography>
                                    <Typography>description 2 // get value from JSON</Typography>
                                </Paper>
                            </TimelineContent>
                        </TimelineItem>

                        <TimelineItem>
                            <TimelineOppositeContent>
                                <Typography variant="body2" color="textSecondary">
                                    10:00 am // get value from JSON
                                </Typography>
                            </TimelineOppositeContent>
                            <TimelineSeparator>
                                <TimelineDot color="primary">
                                    <BusinessCenter />
                                </TimelineDot>
                                <TimelineConnector />
                            </TimelineSeparator>
                            <TimelineContent>
                                <Paper elevation={3} className={classesTimeline.paper}>
                                    <Typography variant="h6" component="h1">
                                        title 3 // get values from JSON
                                    </Typography>
                                    <Typography>description 3 // get value from JSON</Typography>
                                </Paper>
                            </TimelineContent>
                        </TimelineItem>

                    </Timeline>

Is it possible to set all values from JSON object and set also Paper component color based on JSON value using Typescript? When I have "approved": true to set green color for Paper background.

2 Answers

Yea you could and its simpler than you might think. There are two main options in achieving this:

  1. propagating props - meaning passing the values you need as props for the component that holds the timeline as one of its children:
<ComponentWithTimeline steps={<stepsJsonVariableName>}/>

styling part of the timeline component

classesTimeline:{
    ...classesTimeline
    greenPaper:
    {
        ...classesTimeline.paper,
        backgroundColor: "green",
    }
}

Timeline part of component


                     <Timeline align="alternate">
                        <TimelineItem>
                            <TimelineOppositeContent>
                                <Typography variant="body2" color="textSecondary"> // get color form Json
                                    9:30 am  // get this value from JSON
                                </Typography>
                            </TimelineOppositeContent>
                            <TimelineSeparator>
                                <TimelineDot>
                                    <LibraryBooks />
                                </TimelineDot>
                                <TimelineConnector />
                            </TimelineSeparator>
                            <TimelineContent>
                                <Paper elevation={3} className={(props.steps.step1.approved) ? classesTimeline.greenPaper : classesTimeline.paper}>
                                    <Typography variant="h6" component="h1">
                                        {props.steps.step1.title}
                                    </Typography>
                                    <Typography> {props.steps.step1.description}</Typography>
                                </Paper>
                            </TimelineContent>
                        </TimelineItem>

                        <TimelineItem>
                            <TimelineOppositeContent>
                                <Typography variant="body2" color="textSecondary">
                                    11:00 am // get this value from JSON
                                </Typography>
                            </TimelineOppositeContent>
                            <TimelineSeparator>
                                <TimelineDot color="primary">
                                    <PeopleAlt />
                                </TimelineDot>
                                <TimelineConnector />
                            </TimelineSeparator>
                            <TimelineContent>
                                <Paper elevation={3} className={(props.steps.step.approved) ? classesTimeline.greenPaper : classesTimeline.paper}>
                                    <Typography variant="h6" component="h1">
                                        {props.steps.step2.title}
                                    </Typography>
                                    <Typography>{props.steps.step2.description}</Typography>
                                </Paper>
                            </TimelineContent>
                        </TimelineItem>

                        <TimelineItem>
                            <TimelineOppositeContent>
                                <Typography variant="body2" color="textSecondary">
                                    10:00 am // get value from JSON
                                </Typography>
                            </TimelineOppositeContent>
                            <TimelineSeparator>
                                <TimelineDot color="primary">
                                    <BusinessCenter />
                                </TimelineDot>
                                <TimelineConnector />
                            </TimelineSeparator>
                            <TimelineContent>
                                <Paper elevation={3} className={(props.steps.step3.approved) ? classesTimeline.greenPaper : classesTimeline.paper}>
                                    <Typography variant="h6" component="h1">
                                        {props.steps}
                                    </Typography>
                                    <Typography>{props.steps.step3.description}
</Typography>
                                </Paper>
                            </TimelineContent>
                        </TimelineItem>

                    </Timeline>
  1. using react context to make the value of the json object available to all child objects (docs)

basic example:

// Context lets us pass a value deep into the component tree
// without explicitly threading it through every component.
// Create a context for the current theme (with "light" as the default).
const ThemeContext = React.createContext('light');

class App extends React.Component {
  render() {
    // Use a Provider to pass the current theme to the tree below.
    // Any component can read it, no matter how deep it is.
    // In this example, we're passing "dark" as the current value.
    return (
      <ThemeContext.Provider value="dark">
        <Toolbar />
      </ThemeContext.Provider>
    );
  }
}

// A component in the middle doesn't have to
// pass the theme down explicitly anymore.
function Toolbar() {
  return (
    <div>
      <ThemedButton />
    </div>
  );
}

class ThemedButton extends React.Component {
  // Assign a contextType to read the current theme context.
  // React will find the closest theme Provider above and use its value.
  // In this example, the current theme is "dark".
  static contextType = ThemeContext;
  render() {
    return <Button theme={this.context} />;
  }
}

You could conditionally inject a className based on the approved field,
here's an example of what the extracted component could look like:

const YourCustomComp = (x: {approved: boolean; approvalTime: string; title: string; description: string}) => (
  <>
     ....
     <Paper elevation={3} className={`${classesTimeline.paper} ${x.approved ? 'greenSelector' : ''} `>
        <Typography variant="h6" component="h1">
           {x.title}
        </Typography>
        <Typography> {x.description} </Typography>
     </Paper>
     ....
  </>
)

There is also a utility called clsx that was created for cases like this, I suggest you take a look at it.

Related