Search code examples
javascriptreactjstypescriptmaterial-uireact-typescript

Generate Material Timeline from JSON Object


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.


Solution

  • 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} />;
      }
    }