Create a Material-UI Rich Text Editor in React

How to create Material UI Editor in React


So far we have seen many Editor Frameworks and their usage guides. As a React fan you may miss the MUI library. The mui-rte is Material UI RichText editor and viewer.

The editor was built on top of draft-js and supports use defined blocks, styles, autocomplete strategies, async/sync custom atomic blocks, callbacks, and decorators as well as toolbar and theme customization to enhance the editor to all needs.

Let’s quickly setup a React project and install the dependencies.

npx create-react-app myapp
yarn add mui-rte @mui/material @mui/icons-material @mui/styles @emotion/react @emotion/styled 

Make sure all the dependencies and peer dependencies properly added.

import { createTheme, ThemeProvider } from "@mui/material/styles";
import MUIRichTextEditor from "mui-rte";

const MuiEditor = () => {
  const save = (data) => {
    console.log(data);
  };
  const myTheme = createTheme({
    // Set up your custom MUI theme here
  });

  return (
    <div className="editorContainer">
      <ThemeProvider theme={myTheme}>
        <MUIRichTextEditor
          label="Type something here..."
          onSave={save}
          inlineToolbar={true}
        />
      </ThemeProvider>
    </div>
  );
};

export default MuiEditor;

Open the example in Sandbox.

How to customize theme in Material UI

How to customize Material UI themes in Reactjs


Material UI is the #1 UI for Reactjs and it continues it journey. Can I customize theme in MUI ?

With custom theme object we can create and implement the theme for any component or a group of component using a wrapper component. We require the following

  • createTheme
  • ThemeProvider

CreateTheme

     const theme = createTheme(
        {
            palette:
                { mode: 'light'}
        }
    );

We can customize the them using the createtheme function.

ThemeProvider

With the ThemeProvider we can provide theme for the component tree. It take a theme as prop.

 return (
        <div>
            <ThemeProvider theme={theme} >
                {props.children}
            </ThemeProvider>
        </div>
    )

Create Mui Dark Mode switch using React Context

How to creaye dark theme switch in using Material UI switch and React Context and State Hooks


Material UI or MUI is one word for all UI needs. It is well documented and easy to use. I really enjoyed it.

In this post I would like to demonstrate how to create dark-mode switcher using the React Context and Material UI switch component.

Context

We already covered the dynamic-Context in detail, please use the posts to learn more about Context and the basic step required.

Our context setup with look like the following

//context/themeContext.js
 import React from 'react';

export const ThemeContext = React.createContext({
    theme: 'dark',
    setTheme: () => { }
  })
  
//app.js or _app.js
 
import React, { useState } from 'react'; 
import { ThemeContext } from '../context/themeContext';


function MyApp({ Component, pageProps }) {
  const [theme, setTheme] = useState("light")
  const value = { theme, setTheme };
 

  return (
  
      <ThemeContext.Provider value={value}   >
        <Component {...pageProps} />
      </ThemeContext.Provider>
    
  );
}

Theme Switcher

A MUI customized switch can be used to create a theme switcher. We also need to access the context using the useContext hook. The code will look like the following.

The complete switch snippet can be obtained from Material UI switch documentation page.

import * as React from 'react';
import clsx from 'clsx';
import { styled } from '@mui/system';
import { useSwitch } from '@mui/core/SwitchUnstyled';
import { Tooltip } from '@mui/material';
import { ThemeContext } from '../context/themeContext';
 ...
function MUISwitch(props) {
  const { theme, setTheme } = React.useContext(ThemeContext)
  const { getInputProps, checked, disabled, focusVisible } = useSwitch(props);
  const stateClasses = {
    checked,
    disabled,
    focusVisible,
  };
  var mode = {

  };

 
  React.useEffect(() => {
    const mode = stateClasses.checked ? 'dark' : 'light'
    setTheme(mode)
  }, [stateClasses])
  return (
    <Tooltip title="Theme switcher">
      <SwitchRoot className={clsx(stateClasses)} >
        <SwitchTrack>
          <SwitchThumb className={clsx(stateClasses)} />
        </SwitchTrack>
        <SwitchInput {...getInputProps()} aria-label="Demo switch" />
      </SwitchRoot>
    </Tooltip>

  );
}

export default function UseSwitchesCustom() {
  return <MUISwitch defaultChecked />;
}

The switcher component can be placed anywhere in component tree and it can change the context value, due to dynamic context.

Tracking changes

In order observe changes in state of the switch component , we can use useEffect and the stateClass. Note that there is no event handler attached to the component.

Implement the Theme

The theme can be implemented as you wish, one of the suggested way is to create a component to implement the theme and wrap other components inside it. Such a component can be .

mport React from 'react'
import { createTheme, ThemeProvider, styled } from '@mui/material/styles';
import { ThemeContext } from '../context/themeContext';

export default function BaseTheme(props) {
    const { theme, setTheme } = React.useContext(ThemeContext)
    const theme1 = createTheme(
        {
            palette:
                { mode: theme }
        }
    );

    console.log('Current Theme - ' + JSON.stringify(theme));
    return (
        <div>
            <ThemeProvider theme={theme1} >
                {props.children}
            </ThemeProvider>
        </div>
    )
}

That’s it.

Leave comment and questions

How to enable validation on visited fields in Formik

How to enable validation in visited fields in Formik


We can make form validation of our own with custom hook, but there is a good library for that already, Formik.

Formik provide useForm hook for implementing the validation into our regular form.

Visited field

In input fields in a form get validated using onChange handler provided by the hook, for visited fields Fomik provides onBlur handler.

   const formik = useFormik({
    initialValues: {
      email: '',
      name: '',
      password: 'foobar',
      cid: '',
      lid: ''
    },
    validate,
  onSubmit: (values) => {

In the form field we can use handler as

 <TextField
                    
                    onBlur={formik.handleBlur}
                    
                    error={formik.touched.name && Boolean(formik.errors.name)}
                    helperText={formik.touched.name && formik.errors.name}
                    autoFocus
                  />

Integrating Formik with Form and Mui so easy, isn’t it? Follow posts may help you learn more on the go.

Integrate Formik validation with Mui Form in React

How integrate Mui with React


We can make form validation of our own with custom hook, but there is a good library for that already, Formik.

Formik provide useForm hook for implementing the validation into our regular form. The first step of using Formik is installing the dependency, lol, also we need a validator function to perform validation.

const validate = values => {
  const errors = {};

  if (!values.password) {
    errors.password = 'Required';
  } else if (values.password.length < 6) {
    errors.password = 'Must be must be 6 or more characters';
  }
  if (!values.name) {
    errors.name = 'Name Required';
  } else if (values.name.length < 1) {
    errors.name = 'Minimum of 2 characters';
  }
}

It is just another JavaScript function, which check the parameter value and return some object.

useFormik

Let’s create Formik object,

const formik = useFormik({
    initialValues: {
      email: 'martin@gmail.com',
      name: 'Martin Thomas',   
    },
    validate,
    onSubmit: (values) => {
       alert(JSON.stringify(values, null, 2));
    },
  });

The useForm hook provide handleSubmit, handleChange, handleBlur, isSubmiting event handlers and properties’ , where handleBlur watching the revisited input change and the isSubmiting return true if there is no error.

Initial values

Create initial values for the form input, it can be expressed as simple object

Validate

Validation can be schema , or a function, we can also use external libraries such as yum for schema generation. For our case it is a function

const validate = values => {
  const errors = {};

  if (!values.password) {
    errors.password = 'Required';
  } else if (values.password.length < 6) {
    errors.password = 'Must be must be 6 or more characters';
  }
  if (!values.name) {
    errors.name = 'Name Required';
  } else if (values.name.length < 1) {
    errors.name = 'Minimum of 2 characters';
  }
  if (!values.email) {
    errors.email = 'Required';
  } else if (!/^[A-Z0-9._%+-]+@[A-Z0-9.-]+\.[A-Z]{2,4}$/i.test(values.email)) {
    errors.email = 'Invalid email address';
  }
  if (!values.lid) {
    errors.lid = 'Required';
  }

  if (!values.cid) {
    errors.cid = 'Required';
  }

  return errors;
};

onSubmit

We can wrap submission logic in this handler.

Add validation to the form

In the form section we can us the handlers as formik.handlerName also the value can can be accessed from the value Object. The error object can be use to display the error messages.

import React from 'react';
import { useFormik } from 'formik';
import Button from "@mui/material/Button"; 
import CssBaseline from "@mui/material/CssBaseline";
import TextField from "@mui/material/TextField"; 
import Grid from "@mui/material/Grid";
import Box from "@mui/material/Box"; 
import Typography from "@mui/material/Typography";
import Container from "@mui/material/Container";
import { createTheme, ThemeProvider } from "@mui/material/styles";

 
.... 
const formik = useFormik({
    initialValues: {
      email: 'martin@gmail.com',
      name: 'Martin Thomas',   
    },
    validate,
    onSubmit: (values) => {
       alert(JSON.stringify(values, null, 2));
    },
  });
<div>
      <ThemeProvider theme={theme}>
        <Container component="main" maxWidth="xs">
          <CssBaseline />
          <Box
            sx={{
              marginTop: 8,
              display: "flex",
              flexDirection: "column",
              alignItems: "center",
            }}
          >
            
            <Box
              component="form"
              onSubmit={formik.handleSubmit}
              sx={{ mt: 3 }}
            >

              <Grid container spacing={2}>
                <Grid item xs={12} sm={12}>
                  <TextField
                    autoComplete="given-name"
                    name="name"
                    required
                    fullWidth
                    id="name"
                    label="Name"
                    onBlur={formik.handleBlur}
                    value={formik.values.name}
                    onChange={formik.handleChange}
                    error={formik.touched.name && Boolean(formik.errors.name)}
                    helperText={formik.touched.name && formik.errors.name}
                    autoFocus
                  />
                </Grid>

                <Grid item xs={12}>
                  <TextField
                    required
                    fullWidth
                    id="email"
                    onBlur={formik.handleBlur}
                    label="Email Address"
                    name="email"
                    autoComplete="email"
                    value={formik.values.email}
                    onChange={formik.handleChange}
                    error={formik.touched.email && Boolean(formik.errors.email)}
                    helperText={formik.touched.email && formik.errors.email}
                  />
                </Grid>
                  
              
              <Button
                type="submit"
                 disabled={formik.isSubmitting}
                fullWidth
                variant="contained"
                sx={{ mt: 3, mb: 2 }}
              >
                Sign Up
              </Button>
              

            </Box>
          </Box>      
        </Container>
      </ThemeProvider>       
    </div>

Integrating Formik with Form and Mui so easy.

How to set margin in React MUI component

How to set margin in React Material UI components


Material UI /MUI is one word for all React UI needs, as we know. Let’s learn how set margin in a basic box container.

In MUI React component we can use sx property to customize styles. For margin have to use m, mt / ml options.

  <Box sx={{ mt: 1 }}>
.....

This will set the margin top of the Box to 1.