How messages get exchanged between Docker containers

Now-a-days Since almost all applications employ containers, it goes without saying that they will need to communicate with one another. In this article, we will cover how messages may be easily sent and received between containers.

I’m assuming that your environment already has Docker installed. Next, we’ll build two apps with flask and node js and attempt to communicate between them.

Let’s start with a Python app that uses Flask.

Create a folder called “ping-app” and create app.py file, place the following code in it.

from flask import Flask
from redis import Redis

app = Flask(__name__)
redis = Redis(host='redis', port=6379)

@app.route('/')
def home():
    redis.incr('pageviews')
    return 'This app has been viewed %s time(s).' % redis.get('pageviews')


@app.route('/get-redis-count')
def count():
    return redis.get('pageviews')


if __name__ == "__main__":
    app.run(host="0.0.0.0", debug=True)

We can see from the code above that Redis is being used as a key-value pair database. and on the root route, we are returning a message with the count to print on the screen while also increasing the number of pageviews in redis by 1.

Since this application uses two packages, let’s make a requirements.txt file and include the following dependencies:

flask
redis

Now Create a file called Dockerfile and add the following code to begin dockerizing this application:

FROM python:3.7
ADD . /code
WORKDIR /code
RUN pip install -r requirements.txt
CMD python app.py

For the next step, we will need a docker-compose file with the following code in order to properly execute this application: Create a docker-compose.yaml file and add the following code:

version: "3.9"
services:
    web:
        build:
          context: .
          dockerfile: Dockerfile
        ports:
            - "5000:5000"
        volumes:
            - .:/code
        depends_on:
            - redis
    redis:
        image: redis

In this code we can see that we have 2 services, 1 is web which is basically using our docker file to run our already created flask app and another service is redis, which basically runs on 6379 port by default. So lets run the app now using following command in your workspace terminal.

docker-compose up

Your redis and web services will both become operational as a result.
Using http://localhost:5000, let’s open your flask application now on browser. and whoohoo, the results are displayed as shown.

Now Reload this app in your browser now a number of times to observe if the count increases each time the page loads.

Also Check out the other endpoint in the same app, http://localhost:5000/get-redis-count, which simply returns the screen count number value.

So far, everything has been rather simple. Let’s assume that you have another Node.js application that wishes to receive the pageview count.

let’s make that Node App as well utilising the techniques below:

Make a new folder called pong-app as a sibling to ping-app, and then place a package.json file containing the following information:

{
    "name": "pong-app",
    "version": "1.0.0",
    "description": "",
    "author": "Jeetendra Singh <[email protected]>",
    "main": "app.js",
    "scripts": {
        "start": "node app.js"
    },
    "dependencies": {
        "axios": "^1.1.2",
        "express": "^4.16.1"
    }
}

After this lets create app.js file parallel to package.json file with following code:

const express = require('express');
const axios = require('axios');
// Constants
const PORT = 8000;
const HOST = '0.0.0.0';

// App
const app = express();
app.get('/', (req, res) => {
  res.send('Hello Node');
});

app.listen(PORT, HOST, () => {
  console.log(`Running on http://${HOST}:${PORT}`);
});

The code above is simply the beginning of a small express application. Hello Node, let’s first dockerize this application. thus make a Dockerfile file with the following information in it.

FROM node:16 
WORKDIR /usr/app
COPY package*.json ./
RUN npm install
COPY . .
CMD node app.js

Lets create a docker-compose.yaml file for this app with following information:

version: "3.9"
services:
    server:
        build:
          context: .
          dockerfile: Dockerfile
        ports:
            - "8000:8000"
        volumes:
            - .:/usr/app
            - /usr/app/node_modules

You are now prepared for this app, docker-compose up can be used to start an application, which will then run on http://localhost:8000. and on the root route, it will output Hello Node.

Now that both apps are operating in separate containers, the easiest approach to display the number of pageviews for the Python app in the node js app is to access the /get-redis-count API on the existing Flask app.
Let’s create a function in Node.js to retrieve the pageview count from a Flask application using the existing Flask api.

app.get("/get-data-from-ping-app",async (req,res)=>{ 
  //call flask based api
  try{
    const response= await axios.get('http://web:5000/get-redis-count')
    console.log('redis count in flask app is ',response.data)
    res.json({count:response.data})
  }catch(err){
    const error='Node App is not able to connect with flask app';
    console.log(error)
    res.send(error)
  }
})

We are attempting to call the departing endpoint /get-redis-count running inside the Flask app in the aforementioned code.


Also, if you’ve observed, we used web:5000 instead of localhost:5000 when creating the url for the flask app (http://web:5000/get-redis-count). Therefore, in order to access resources within containers using the http protocol, we must utilise the container service name defined in the compose file. The service name for this Flask app is web, which is why the url is web:5000.

Now let’s restart our node app and test whether we still obtain the desired results by accessing http://localhost:8000/get-data-from-ping-app.

Currently, the output message will read: Node App is unable to connect with Flask App.

But why? Because there is no networking between the two apps, which are running independently. Therefore, we need to make a few changes to both apps in order to create a network between them.

Just before services, add the network my-local-net with a driver bridge to the docker-compose.yaml file of both apps(ping & pong).

networks:
 my-local-net:
  name: my_local_net
  driver: bridge

Add the following code to the services section of both docker-compose files to connect the created network to each service.

 networks:
       - my-local-net

Let’s take a last glance at the docker-compose files:

Ping App’s docker-compose.yaml file(Flask based app)

version: "3.9"
networks:
 my-local-net:
  name: my_local_net
  driver: bridge
services:
    web:
        build:
          context: .
          dockerfile: Dockerfile
        ports:
            - "5000:5000"
        networks:
            - my-local-net
        volumes:
            - .:/code
        depends_on:
            - redis
    redis:
        image: redis
        networks:
            - my-local-net

Pong App’s docker-compose.yaml file(Node.js based app)

version: "3.9"
networks:
 my-local-net:
  name: my_local_net
  driver: bridge
services:
    server:
        build:
          context: .
          dockerfile: Dockerfile
        ports:
            - "8000:8000"
        networks:
            - my-local-net
        volumes:
            - .:/usr/app
            - /usr/app/node_modules

Restart both apps now, then try to access the following URL to view pageviews for the flask app in Node.js:

http://localhost:8000/get-data-from-ping-app

It will respond with something like

{“count”:x}

Note: that x is merely a stand-in for count, which will be an integer value.

Finally, since they are all declared under the same network, separate apps running in Docker containers can connect with one another using Network Driver Bridge.

From our download center, you can get the complete source code. Additionally, if you have any questions, please comment below. or email me on [email protected]

How to Create a custom PopUp Component in React

In this blog we will learn how to create a custom PopUp Component in React. Our Focus will be on creating a Reusable Component that we can Invoke from any of the component entire our project.

So Let’s follow the steps to create this component.

Step 1: Create a file named custom-popup.module.css with following code

.overlay {
  visibility: hidden;
  opacity: 0;
  position: fixed;
  top: 0;
  bottom: 0;
  left: 0;
  right: 0;
  background: rgba(0, 0, 0, 0.7);
  transition: opacity 500ms;
}
.popup {
  margin: 70px auto;
  padding: 20px;
  background: #fff;
  border-radius: 5px;
  width: 30%;
  position: relative;
  transition: all 5s ease-in-out;
}

.popup h2 {
  margin-top: 0;
  color: #333;
  font-family: Tahoma, Arial, sans-serif;
}
.popup .close {
  position: absolute;
  top: 20px;
  right: 30px;
  transition: all 200ms;
  font-size: 30px;
  font-weight: bold;
  text-decoration: none;
  color: #333;
}
.popup .close:hover {
  cursor: pointer;
  color: #000;
}
.popup .content {
  max-height: 30%;
  overflow: auto;
}

@media screen and (max-width: 700px) {
  .popup {
    width: 70%;
  }
}

In this file we have created all the relevant css that will be needed in our component

Step 2: Now create Popup Component with name CustomPopup.jsx with following code


import { useEffect, useState } from "react";
import popupStyles from "./custom-popup.module.css";
import PropTypes from "prop-types";
const CustomPopup = (props) => {
  const [show, setShow] = useState(false);

  const closeHandler = (e) => {
    setShow(false);
    props.onClose(false);
  };

  useEffect(() => {
    setShow(props.show);
  }, [props.show]);

  return (
    <div
      style={{
        visibility: show ? "visible" : "hidden",
        opacity: show ? "1" : "0"
      }}
      className={popupStyles.overlay}
    >
      <div className={popupStyles.popup}>
        <h2>{props.title}</h2>
        <span className={popupStyles.close} onClick={closeHandler}>
          &times;
        </span>
        <div className={popupStyles.content}>{props.children}</div>
      </div>
    </div>
  );
};

CustomPopup.propTypes = {
  title: PropTypes.string.isRequired,
  show: PropTypes.bool.isRequired,
  onClose: PropTypes.func.isRequired
};
export default CustomPopup;

This will be our component code where we are maintaining the popup opening and closing states on various events. Also we are using propTypes Module to validate our Props. make sure you have installed prop-types module using following npm command

npm install prop-types --save

Step 3: Invocation from another component

<CustomPopup
        onClose={popupCloseHandler}
        show={visibility}
        title="Hello Jeetendra"
      >
        <h1>Hello This is Popup Content Area</h1>
        <h2>This is my lorem ipsum text here!</h2>
      </CustomPopup>

It will need 3 props :
1: onClose – need a handler to do some activity after close click in popup itself
2: show – pass the visibility of popup suing boolean true or false
3: title – provide the popup title


and Inside the you may pass any valid JSX that you want to render as content of popup

If you need a complete example how can we do utilise this PopUp Component then you may look into following code


import { useState } from "react";
import CustomPopup from "./CustomPopup";
import "./styles.css";

export default function App() {
  const [visibility, setVisibility] = useState(false);

  const popupCloseHandler = (e) => {
    setVisibility(e);
  };

  return (
    <div className="App">
      <button onClick={(e) => setVisibility(!visibility)}>Toggle Popup</button>

      <CustomPopup
        onClose={popupCloseHandler}
        show={visibility}
        title="Hello Jeetendra"
      >
        <h1>Hello This is Popup Content Area</h1>
        <h2>This is my lorem ipsum text here!</h2>
      </CustomPopup>
    </div>
  );
}

Hurray we are all set, It will look like following screenshot

react custom popup component


Thats it for this blog. you may reach out to me in case you have any doubts and suggestions please let me know in comments section.

Thanks

Understand Nested Routing in React – React Routing Part-2

In this blog we will understand Nested Routing in React. First we will discuss the Nested routing and its use cases.

Also Guys if you haven’t read Routing in React – Part 1 then click Here as this Blog is part 2 of that blog.


Suppose we have a Blog Page where all blogs will be listed and if user clicked on any blog link the its details page needs to open under blog
as parent slug with its title.

for Example, Blog Page Url is : http://localhost/blog

is will list all of the blog titles like this :

Tutorial 1
or
Tutorial 2

and if we click on these titles then url would be like this :

http://localhost/blog/tutorial-1
or
http://localhost/blog/tutorial-2

and these url are basically nested urls as both of them comes under /blog scheme so this kind of scenarios can be handled via nested routing.

So let’s get started :

In our Exiting App.jsx, Add a menu for Blog after Home menu :

const menuData = [
    {
      title: "Home",
      url: "/"
    },
    {
      title: "Blog",
      url: "/blog"
    },
    {
      title: "Our Services",
      url: "/page/services"
    },
    {
      title: "About Us",
      url: "/page/about"
    },
    {
      title: "Contact Us",
      url: "/page/contact"
    }
  ]

Note: Here the menuData was already presented (in previous Routing Blog), We have just added Blog after Home.

here we have added 1 more menu named Blog after Home

Create a Route for Blog In Exiting Switch

<Route path="/blog">
             <Blog />
          </Route>

Note : as of now we dont have Blog component so we will create it in next step.

Now Create a Blog Component named Blog.js which uses Nested Routing in React :

import { Link, Route, Switch, useRouteMatch } from "react-router-dom";
import Detail from "./Detail";
const Blog = () => {
  let match = useRouteMatch();

  return (
    <div>
      <h1>Blogs</h1>
      <ul>
        <li>
          <Link to={`${match.url}/tutorial-1`}>Tutorial 1</Link>
        </li>
        <li>
          <Link to={`${match.url}/tutorial-2`}>Tutorial 2</Link>
        </li>
      </ul>
      <Switch>
        <Route path={`${match.path}/:slug`}>
          <Detail />
        </Route>
      </Switch>
    </div>
  );
}
export default Blog;

In above code we are using useRouteMatch to read the current matched url means it is reading till /blog of the url that is current route and we have create 1 new switch with following route :

<Route path={`${match.path}/:slug`}>
    <Detail />
</Route>

So its means if we get any other slug after current slug (/blog), then that should load the component Detail(this component we will create in next step.)

So basically we have created a nested route in blog route in Blog Component itself.

Now lets create a Detail Component named Detail.js like this :

import { useParams } from "react-router-dom";
const Detail = () => {
    const blogData=[
        {
            slug:'tutorial-1',
            title:'Tutorial 1',
            details:'Contrary to popular belief, Lorem Ipsum is not simply random text. It has roots in a piece of classical Latin literature from 45 BC, making it over 2000 years old. Richard McClintock, a Latin professor at Hampden-Sydney College in Virginia, looked up one of the more obscure Latin words, consectetur, from a Lorem Ipsum passage, and going through the cites of the word in classical literature, discovered the undoubtable source. Lorem Ipsum comes from sections 1.10.32 and 1.10.33 of "de Finibus Bonorum et Malorum" (The Extremes of Good and Evil) by Cicero, written in 45 BC. This book is a treatise on the theory of ethics, very popular during the Renaissance. The first line of Lorem Ipsum, "Lorem ipsum dolor sit amet..", comes from a line in section 1.10.32.'
        },
        {
            slug:'tutorial-2',
            title:'Tutorial 2',
            details:'Lorem Ipsum is simply dummy text of the printing and typesetting industry. Lorem Ipsum has been the industry standard dummy text ever since the 1500s, when an unknown printer took a galley of type and scrambled it to make a type specimen book. It has survived not only five centuries, but also the leap into electronic typesetting, remaining essentially unchanged. It was popularised in the 1960s with the release of Letraset sheets containing Lorem Ipsum passages, and more recently with desktop publishing software like Aldus PageMaker including versions of Lorem Ipsum.'
        }
    ]
    const {slug} = useParams();
    const pageData = blogData.find(r=>r.slug===slug)
    return (
       <div>
           <h1>{pageData.title}</h1>
           <div>
                {pageData.details}
           </div>
       </div>
    )
}
export default Detail;

In this component we are using useParams() hook to read the available parameters in url, and we are reading slug and finding in our data with that slug and showing the relevant details.

let see how our application looks like now :

Hope you understand the routing to download the full source code please click here.

If you face any issues then let me know in comments section. also suggestions are most welcome.

Create a Simple App to Understand Routing in React

In this blog we will create a simple application to understand Routing in React. So basically here we will use a package react-router-dom to implement routing in our application.

This App will be able to load relevant component on a particular url routing, Also we will create a dynamic Page Component that will handle Dynamic Page Routing as well.

I am assuming you have already created a React App, Now lets Start the Routing implementation Step by Step :

Step 1: Install React router dom

npm install react-router-dom --save 

Step 2 : We will create a component to show navigation in top of our App, So Create Header.js file with following code :

import { Link } from "react-router-dom";
const Header = props => {
return (
    <div className="headerNav">
        {props?.menus && props.menus.map( (m,index)=>(
            <div className="menuItem" key={index}><Link to={m.url} >{m.title}</Link></div>
        ))}
    </div>
)
}
export default Header;

If you have notices we have Imported and used Component from React Router Dom, So If React Routing We should not use <a> anchor tags, as it reloads the whole page again and In any client side application this is not recommended. tag itself render same as anchor except it doesn’t reload the whole page.

This component will basically will be used to display header menus. also we can see that we are running loop over props.menus, so it means that we will need to pass menus wherever we call this Header component.

Now lets add some css in your already existing css file App.css :

.headerNav{
  background-color:#000;;
  color:#fff;
  width:100%;
  height:25px;
  padding:10px
}
.menuItem{
  display:inline;
  padding:10px
}
.menuItem a{
  color:#fff;
  text-decoration: none;
  cursor:pointer;
}

Step 3 : Create a Home Component named Home.js that will show our Home page on our root url :

const Home = () => {
    return (
       <div>
           <h1>Home page title</h1>
           <div>
               This is dummy home page text here
           </div>
       </div>
    )
}
export default Home;

Above is simple a Component that renders 1 title and description.

Step 4: Create a dynamic page named Page.js that will handle dynamic pages according to url parameters :

import { useParams } from "react-router-dom";
const Page = () => {
    const staticData=[
        {
            slug:'services',
            title:'Our Services',
            description:'This is our services page description'
        },
        {
            slug:'about',
            title:'About Us',
            description:'This is about us page description'
        }
    ]
    const {slug} = useParams();
    const pageData = staticData.find(r=>r.slug===slug)
    return (
       <div>
           <h1>{pageData.title}</h1>
           <div>
                {pageData.description}
           </div>
       </div>
    )
}
export default Page;

Understand Dynamic Page Component

In this Component we are using a Hook named useParams(), this is a function that we have imported from react-router-dom itself that just reads the parameter passed in url for specific route. and behalf of this parameter we are find and showing from our static data for multiple pages. in real scenario this data may come from api as well.

Step 5: Now lets work on App.js to configure the Routes, Lets update the App.js code as following :

import React from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import './App.css';
import Header from './Header';
import Home from './Home';
import Page from './Page';
const App = () => {

  const menuData = [
    {
      title: "Home",
      url: "/"
    },
    {
      title: "Our Services",
      url: "/page/services"
    },
    {
      title: "About Us",
      url: "/page/about"
    },
    {
      title: "Contact Us",
      url: "/page/contact"
    }
  ]
  return (
    <div className="App"> 
      <Router>
        <Header menus={menuData} />
        <Switch> 
          <Route path="/page/:slug">
             <Page />
          </Route>
          <Route path="/">
             <Home />
          </Route>
        </Switch>
      </Router>
    </div>
  );
}
export default App;

Understanding App.js Code In Detail

In this code initially we have imported these 3 components like this :

import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';

First Component is Browser Router that we have aliased as Router, this will be our Root Component of routing implementation So we will wrap the whole routing related stuff in this Component

Second Component is Route that will use for defining the url Route and where(On which Component) that Route will land

Third Component is Switch that will be a Wrapper required on All Routes to decide which route is matched with url

Also you can see we have created a menuData and passed this as menus property of Header component, So In Header component we have already handled the menus from props and print it accordingly

Now lets understand the Switch in our Jsx :

 <Switch> 
          <Route path="/page/:slug">
             <Page />
          </Route>
          <Route path="/">
             <Home />
          </Route>
        </Switch>

In this switch, First Routes is dynamic url and defined as /page/:slug where slug is variable name, can captured in Page Component using useParams() hook. and In this Route component, we have passed Component so it means when this route matches then Load the Page Component.

Second Route is straigt forward for handle Root Url and It will Land on Home component as defined.

let see how its Looks in action :

Thats it folks, If you face any trouble in setup this demo let me know in comments Section. I will be happy to help you. Suggestions are also Welcome.

To download the Source Code Click Here.

Checkout Part 2 of this blog where we have discussed about Nested Routing.

Simple Component for Multilevel Sidebar Menus in React

In this blog we will create a simple component for Multilevel sidebar menus in React. This will a reusable component that will receive data as props and render the sidebar navigation menus which supports N level of depth.

My Assumption is you are familiar with React Router Dom and its usage as I am using React Router Dom for Routing purpose in this application.

So let’s get Started :

Step 1: Create a Css File names MultilevelSideNav.css and put following code :

.multilevelSideNav {
  height: 100%;
  width: 0;
  position: fixed;
  z-index: 1;
  top: 0;
  left: 0;
  background-color: #111;
  overflow-x: hidden;
  padding-top: 60px;
}

.multilevelSideNav a {
  padding: 8px 8px 8px 32px;
  text-decoration: none;
  font-size: 25px;
  color: #818181;
  display: block;
  transition: 0.3s;
}

.multilevelSideNav a:hover {
  color: #f1f1f1;
}

.multilevelSideNav .closebtn {
  position: absolute;
  top: 0;
  right: 25px;
  font-size: 36px;
  margin-left: 50px;
}

@media screen and (max-height: 450px) {
  .multilevelSideNav {padding-top: 15px;}
  .multilevelSideNav a {font-size: 18px;}
}

Step 2: Create a Side Nav Component named MultilevelSideNav.js with following code :

import React, { useState } from 'react';
import { Link } from 'react-router-dom';
import './MultilevelSideNav.css';
const MultilevelSideNav = ({ data, sideNavState, sideNavHandler }) => {

    const [currentMenus, setCurrentMenus] = useState(data);
    const [previousStack, setPreviousStack] = useState([]);
    const renderMenuItems = data => {

        return data.map((item, index) =>
            (item?.children && item?.children.length) ? (
                <Link key={index}
                    onClick={e => {
                        previousStack.push(data);
                        setPreviousStack(previousStack);
                        setCurrentMenus(item.children)
                    }}
                    to={"#"}>{item.name} &gt; </Link>

            ) : <Link key={index} to={item.url}>{item.name}</Link>
        )
    }
    return data && (
        <div style={{ width: (sideNavState) ? '250px' : '0' }} className="multilevelSideNav">
            <Link to={"#"} className="closebtn" onClick={e => sideNavHandler(false)}>&times;</Link>
            {(previousStack.length) ?
                <Link to={"#"} onClick={e => {
                    const prevState = previousStack.pop();
                    setPreviousStack(previousStack);
                    setCurrentMenus(prevState);

                }}>&lt; Back</Link>
                : null
            }
            {
                renderMenuItems(currentMenus)
            }
        </div>
    );
}
export default MultilevelSideNav;

Now we will create 2 components for url handleing 1 for Showing Home page and another for showing
Page relevant information.

Step 3: Create a simple Home Component Home.js Like this:

const Home = () => {
return (
    <h1>This is my Home Page</h1>
  );
}
export default Home;

Step 4: Create a Page Component Page.js that will show a menu Title by its Slug :

import React from 'react'
import { useParams } from 'react-router-dom';
const Page = () => {
    const { slug } = useParams();
    return (
        <h1>This is Page for {slug.replace("menu-","Menu ").replace(/-/g,".")}</h1>
    );
}
export default Page;

Now we are ready to Call our MultilevelSideNav Component that we have created in Step 2

Step 5: lets do the changes in App.js to call MultilevelSideNav Component :

Constructing the menu data, you may grab this data from your api as well

const menuData = [
    {
      name: "Home",
      url: "/"
    },
    {
      name: "Menu 1",
      children: [
        {
          name: "Menu 1.1",
          url: "/page/menu-1-1"
        }
      ]
    },
    {
      name: "Menu 2",
      url: "/page/menu-2"
    },
    {
      name: "Menu 3",
      children: [
        {
          name: "Menu 3.1",
          url: "/page/menu-3-1"
        },
        {
          name: "Menu 3.2",
          url: "/page/menu-3-2"
        },
        {
          name: "Menu 3.3",
          children: [
            {
              name: "Menu 3.3.1",
              url: "/page/menu-3-3-1"
            },
          ]
        }
      ]
    },
    {
      name: "Menu 4",
      children: [
        {
          name: "Menu 4.1",
          url: "/page/menu-4-1"
        },
        {
          name: "Menu 4.2",
          url: "/page/menu-4-2"
        },
        {
          name: "Menu 4.3",
          children: [
            {
              name: "Menu 4.3.1",
              url: "/page/menu-4-3-1"
            },
            {
              name: "Menu 4.3.2",
              url: "/page/menu-4-3-2"
            },
            {
              name: "Menu 4.3.3",
              children: [
                {
                  name: "Menu 4.3.3.1",
                  children: [
                    {
                      name: "Menu 4.3.3.1.1",
                      url: "/page/menu-4-3-3-1-1"
                    }
                  ]
                },
                {
                  name: "Menu 4.3.3.2",
                  url: "/page/menu-4-3-3-2"
                }
              ]
            }
          ]
        }
      ]
    }
  ]

and Finally this will be our JSX return in App.js

return (
    <div className="App">
      <Router>
        <MultilevelSideNav sideNavState={sideNavState} sideNavHandler={setSideNavState} data={menuData} />
        <div style={{marginLeft:(sideNavState)?'250px':'0'}}>
          <h2><span style={{fontSize:'30px',cursor:'pointer'}} onClick={e=>setSideNavState(true)}>&#9776; Open SideNav</span></h2>      
          <Switch> 
          <Route path="/page/:slug">
             <Page />
          </Route>
          <Route path="/">
             <Home/>
          </Route>
        </Switch>
        </div>        
      </Router>
    </div>

Note : As I mentioned earlier as well I am using React Router Dom to handle page click and showing relevant page information once landing to any page

And Finally lets see how our App will look this :

Thats it we have created our multilevel sidebar menus in react js. if you face any issue in creating this component on your system please let me know in comments section. Also Suggestions or Feedbacks for improvement are welcome.

You may Download the complete source code by clicking this link

Simple Component for Multilevel Navigation Menus in React

In this Blog we will create a simple application for Multilevel Navigation Menus in React Js which accepts data through props and display Nth Level Navigation Menus.
Assuming you have already using react-router-dom as we are using that to handle the Routing and Navigation Links in this demo.

So let’s get started :

Step 1: Create a MultilevelMenu.css file and put following css code :

.multilevelMenu ul {
  list-style: none;
  padding: 0;
  margin: 0;
  background: #2c3e50;
}

.multilevelMenu ul li {
  display: block;
  position: relative;
  float: left;
  background: #2c3e50;
}
.multilevelMenu li ul {
  display: none;
}

.multilevelMenu ul li a {
  display: block;
  padding: 1em;
  text-decoration: none;
  white-space: nowrap;
  color: #fff;
}

.multilevelMenu ul li a:hover {
  background: #151e27;
}
.multilevelMenu li:hover > ul {
  display: block;
  position: absolute;
}

.multilevelMenu li:hover li {
  float: none;
}
.multilevelMenu ul ul ul {
  left: 100%;
  top: 0;
}
.multilevelMenu ul:before,
.multilevelMenu ul:after {
  content: " "; /* 1 */
  display: table; /* 2 */
}

.multilevelMenu ul:after { clear: both; }

.multilevelMenu li:hover a {
  background: #2c3e50;
}

.multilevelMenu li:hover li a:hover {
  background: #151e27;
}

.multilevelMenu .main-navigation li ul li {
  border-top: 0;
}

Step 2: Create a Component Named MultilevelMenu.js with following code :


import React from 'react';
import { Link } from 'react-router-dom';
import './MultilevelMenu.css';
const MultilevelMenu = ({ data }) => {
    const renderMenuItems = data => {
        return data.map((item, index) =>
            (item?.children && item?.children.length) ? (<li key={index}><Link to={"#"}>{item.name}</Link><ul>
                {renderMenuItems(item.children)}
            </ul></li>
            ) : <li key={index}><Link to={item.url}>{item.name}</Link></li>
        )
    }
    return data && (
        <div className="multilevelMenu">
            <ul className="main-navigation">
                {renderMenuItems(data)}
            </ul>
        </div>
    );
}
export default MultilevelMenu;

Now your Component is ready but if we click on any menu/url that there should be 2 component, 1 for Home page and 1 for other pages as per url slug passed.

Step 3: Create a simple Home Component Home.js Like this:

const Home = () => {
return (
    <h1>This is my Home Page</h1>
  );
}
export default Home;

Step 4: Create a Page Component Page.js that will show a menu Title by its Slug using following code :

import React from 'react'
import { useParams } from 'react-router-dom';
const Page = () => {
    const { slug } = useParams();
    return (
        <h1>This is Page for {slug.replace("menu-","Menu ").replace(/-/g,".")}</h1>
    );
}
export default Page;

Now we are ready to Call our Multilevel menu Component

Step 5: In this Step we’ll do the changes in App.js File

First add the dummy menus data, you may get similar structure data from api as well if needed.

const menuData = [
    {
      name: "Home",
      url: "/"
    },
    {
      name: "Menu 1",
      children: [
        {
          name: "Menu 1.1",
          url: "/page/menu-1-1"
        }
      ]
    },
    {
      name: "Menu 2",
      url: "/page/menu-2"
    },
    {
      name: "Menu 3",
      children: [
        {
          name: "Menu 3.1",
          url: "/page/menu-3-1"
        },
        {
          name: "Menu 3.2",
          url: "/page/menu-3-2"
        },
        {
          name: "Menu 3.3",
          children: [
            {
              name: "Menu 3.3.1",
              url: "/page/menu-3-3-1"
            },
          ]
        }
      ]
    },
    {
      name: "Menu 4",
      children: [
        {
          name: "Menu 4.1",
          url: "/page/menu-4-1"
        },
        {
          name: "Menu 4.2",
          url: "/page/menu-4-2"
        },
        {
          name: "Menu 4.3",
          children: [
            {
              name: "Menu 4.3.1",
              url: "/page/menu-4-3-1"
            },
            {
              name: "Menu 4.3.2",
              url: "/page/menu-4-3-2"
            },
            {
              name: "Menu 4.3.3",
              children: [
                {
                  name: "Menu 4.3.3.1",
                  children: [
                    {
                      name: "Menu 4.3.3.1.1",
                      url: "/page/menu-4-3-3-1-1"
                    }
                  ]
                },
                {
                  name: "Menu 4.3.3.2",
                  url: "/page/menu-4-3-3-2"
                }
              ]
            }
          ]
        }
      ]
    }
  ]

Now we have the data ready, Next we need to do modify our JSX return Statement like this:

<div className="App">
      <Router>
        <MultilevelMenu data={menuData} />
        <Switch> 
          <Route path="/page/:slug">
             <Page />
          </Route>
          <Route path="/">
             <Home/>
          </Route>
        </Switch>
      </Router>
    </div>

Note : As we have mentioned we are using React Router Dom to handle click on various menus, Home page will show the Home component and All other multi level menus will land on Page component so that all pages can land and show page menu somewhere and we can see the menus in Action

Lets See How finally our App looks Like :

Hope This is Something Helpful to you, In case any suggestions or difficulties please let me know in comments.

TO DOWNLOAD THE WHOLE CODE CLICK ON THIS LINK

React Context Api with Hooks to make Stateful Application

This blog is focused about to create a Stateful Application using React Context Api with Hooks. In this App we will Create a stateful app without using redux or any other third party library.

React Context Api used to share data in React component Tree. So we create Global State or Object to share the Data among Nth level of child and siblings under one root.

In This App we will create a theme changing demo where default theme will be passed from Our Top level Component and child component will be able to use that info. Also from child component we will be able to
update that top level theme data and immediately the update theme will reflect in subsequent child
components.

So lets get Started with following Steps to create a Stateful App using React Context Api with Hooks :

Step 1 : Creating a new React App using CRA, you may skip this if you already having React App setup.
To simply create & run a app named react-context-demo just use following statement in any your CLI

npx create-react-app react-context-demo
cd react-context-demo
npm start

Now you have started the React App and it will look like this :

Step 2: Create a file named AppContext.js using following code :

import React, { createContext } from 'react';
export default const AppContext = createContext();

Step 3: Go to App.js file and replace all code with following code :

import React from 'react';
import './App.css';
const App = () => {
  return (
    <div className="App">
      
    </div>
  );
}
export default App;

Now you have App component in that we will import the provider from our created Context like this

const { Provider } = AppContext;

now create a State for default theme like this :

const [theme, setTheme] = useState({name:'dark',backgroundColor:'black',textColor:'white'});//by default light theme

Now wrap the Div ClassName App using Provider like this :

<Provider value={[theme, setTheme]}>
    <div className="App">
       
       

    </div>
    </Provider>

To use this default theme data we need to create 2 components, so we are creating 1 component to preview the theme and 1 component to update the theme

Step 4: Create a child component (Child.js) that uses the theme data and simply show a message with following code :

import React, { useContext } from 'react';
import AppContext from './AppContext';
const Child = () => {

    const [theme] = useContext(AppContext);
    return (
        <div style={{ backgroundColor: theme.backgroundColor, color: theme.textColor }}>
            <h4>Why do we use it?</h4>
            It is a long established fact that a reader will be distracted by the readable content of 
            a page when looking at its layout. The point of using Lorem Ipsum is that it has a 
            more-or-less normal distribution of letters, as opposed to using 'Content here, 
            content here', making it look like readable English. Many desktop publishing packages 
            and web page editors now use Lorem Ipsum as their default model text, and a search for 
            'lorem ipsum' will uncover many web sites still in their infancy. 
            Various versions have evolved over the years, sometimes by accident, 
            sometimes on purpose (injected humour and the like).
        </div>
    );
}
export default Child;

Now we need to call this component from App component, so returned jsx will look like this :

return (
    <Provider value={[theme, setTheme]}>
    <div className="App">
       <Child />
    </div>
    </Provider>
  );

Lets see how the child component looks now after using the default theme :

Now there is 1 more Step that is required if we want to change the Theme Data/Global Data from any child component, so for that we will make another Toggle component.

Step 5 : Create a Toggle Component to change theme data to override Context Provider’s Default data Make a file named Toggle.Js and use following code in that :


import React, { useContext } from 'react';
import AppContext from './AppContext';
const Toggle = () => {
    const [theme, setTheme] = useContext(AppContext);
    const switchHandler = () => {
        if (theme.name === 'dark') {
            //set light theme
            setTheme({ name: 'light', backgroundColor: 'white', textColor: 'black' })
        } else {
            //set dark theme
            setTheme({ name: 'dark', backgroundColor: 'black', textColor: 'white' })
        }
    }
    return (
        <button
            onClick={switchHandler}
            style={{ backgroundColor: theme.backgroundColor, color: theme.textColor }}>
            Switch to {(theme.name === 'dark') ? "Light" : "Dark"} Theme
        </button>
    );
}
export default Toggle;

Now Use this toggle component in App.js before/After the Child Component, We are calling it before so that it will look on top of child component like this :

return (
    <Provider value={[theme, setTheme]}>
    <div className="App">
       <Toggle />
       <Child />
    </div>
    </Provider>
  );

Let see in Action How its looking.

Now we can see if we click on toggle button then we can easily switch the theme and that theme is also applying on child component immediately.

You may Download the complete source code by clicking this link. Please let me know your thoughts and improvement Ideas over this. Also if you face any kind of difficulties to run or understand that. Please let me know in comments section.

You may Download the complete source code by clicking this link

How to create dynamic fields in React Component

Hey Friends,
In this tutorial we’ll know that how we can create dynamic fields in react js. I hope you are aware with the Installation and setup the React application using CRA utility provided by react.
I am assuming that you have already setup a react project. So lets get start it.

create a file named DynamicForm.jsx and add following basic class syntax in it.

import React, { Component } from "react";

class DynamicForm extends Component {
  
  constructor(props) {
    super(props);
  }

  render() {
      return(
          <h1>My Dynamic Form</h1>
       )
  }
}

Now add some initial state in constructor.

 this.state = {
      form: [
        { fullName: "Manvik Singh", age: 3 },
        { fullName: "Manu Singh", age: 5 }
      ]
    };

Loop through the initial data in render method


        {this.state.form &&
          this.state.form.map((item, index) => (
            <div key={index} className="row mt-5 mb-5">
              <div className="col col-md-5">
                <input
                  placeholder="Full Name"
                  className="form-control"
                  type="text"
                  name="fullName"
                  value={item.fullName}
                  onChange={(e) => this.handleChange(e, index)}
                />
              </div>
              <div className="col col-md-5">
                <input
                  placeholder="Age"
                  className="form-control"
                  type="number"
                  name="age"
                  value={item.age}
                  onChange={(e) => this.handleChange(e, index)}
                />
              </div>
              <div className="col col-md-1">
                <button
                  onClick={() => this.handleDelete(index)}
                  className="btn btn-danger"
                >
                  X
                </button>
              </div>
            </div>
          ))}

Noticed we have used handleChange & handleDelete method in above jsx, so lets create those methods as well


handleChange = (e, index) => {
    const items = this.state.form;
    items[index][e.target.name] = e.target.value;
    this.setState({
      form: items
    });
  };
  handleDelete = (index) => {
    const items = this.state.form;
    if (items.length > 1) {
      items.splice(index, 1);
      this.setState({
        form: items
      });
    } else {
      window.alert("Last row cant be delete!");
    }
  };

Now will need Add new row button and save form button, so let them create before the dynamic form fields are rendering

 <div className="row">
          <div className="col col-md-10 text-right">
            <button onClick={this.addNewRow} className="btn btn-secondary">
              +Add New
            </button>
            <button onClick={this.saveAll} className="ml-2 btn btn-primary">
              Save Form
            </button>
          </div>
        </div>

Now above buttons handlers to handle new row and save the updated/filled form data to api/server.


addNewRow = () => {
    const items = this.state.form;
    const blankRow = { fullName: "", age: "" };
    this.setState({
      form: [...items, blankRow]
    });
  };
  saveAll = () => {
    const { form } = this.state;
    //lets check whats in the form now
    console.log("Form data :", form);
    //Now here you may want to call your service or xhr call to send data over the apis
    //like this
    fetch("https://www.w3school.info/apis/bla-bla-api", form)
      .then((res) => res.json())
      .then((response) => console.log("my response is ", response))
      .catch((err) => console.log("error occured", err));
  };

Now All code at one shot


import React, { Component } from "react";

class DynamicForm extends Component {
  constructor(props) {
    super(props);
    this.state = {
      form: [
        { fullName: "Manvik Singh", age: 3 },
        { fullName: "Manu Singh", age: 5 }
      ]
    };
  }

  handleChange = (e, index) => {
    const items = this.state.form;
    items[index][e.target.name] = e.target.value;
    this.setState({
      form: items
    });
  };
  handleDelete = (index) => {
    const items = this.state.form;
    if (items.length > 1) {
      items.splice(index, 1);
      this.setState({
        form: items
      });
    } else {
      window.alert("Last row cant be delete!");
    }
  };
  addNewRow = () => {
    const items = this.state.form;
    const blankRow = { fullName: "", age: "" };
    this.setState({
      form: [...items, blankRow]
    });
  };
  saveAll = () => {
    const { form } = this.state;
    //lets check whats in the form now
    console.log("Form data :", form);
    //Now here you may want to call your service or xhr call to send data over the apis
    //like this
    fetch("https://www.w3school.info/apis/bla-bla-api", form)
      .then((res) => res.json())
      .then((response) => console.log("my response is ", response))
      .catch((err) => console.log("error occured", err));
  };

  render() {
    return (
      <>
        <h1>My Dynamic Form</h1>
        <div className="row">
          <div className="col col-md-10 text-right">
            <button onClick={this.addNewRow} className="btn btn-secondary">
              +Add New
            </button>
            <button onClick={this.saveAll} className="ml-2 btn btn-primary">
              Save Form
            </button>
          </div>
        </div>
        {this.state.form &&
          this.state.form.map((item, index) => (
            <div key={index} className="row mt-5 mb-5">
              <div className="col col-md-5">
                <input
                  placeholder="Full Name"
                  className="form-control"
                  type="text"
                  name="fullName"
                  value={item.fullName}
                  onChange={(e) => this.handleChange(e, index)}
                />
              </div>
              <div className="col col-md-5">
                <input
                  placeholder="Age"
                  className="form-control"
                  type="number"
                  name="age"
                  value={item.age}
                  onChange={(e) => this.handleChange(e, index)}
                />
              </div>
              <div className="col col-md-1">
                <button
                  onClick={() => this.handleDelete(index)}
                  className="btn btn-danger"
                >
                  X
                </button>
              </div>
            </div>
          ))}
      </>
    );
  }
}
export default DynamicForm;

Now just Import and Add this component where you want we have called it in App Component like this, putting my App.js code


import React from "react";
import DynamicForm from "./DynamicForm";
import "./styles.css";

export default function App() {
  return (
    <div className="App">
      <DynamicForm />
    </div>
  );
}

Note : I have used classes from bootstrap css framework, if you haven’t implemented the bootstrap in your project then you may edit
index.html from public folder and add following bootstrap css cdn link to look this demo fine.

put this in head section

<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.5.2/css/bootstrap.min.css" />

This is all I have for this blog, if you have any queries then let me know me via contact us form or do comments below. Also the live
demo for this code is available at https://codesandbox.io/s/dynamic-form-fields-in-react-y6p3e?file=/src/DynamicForm.jsx

Create Restful CRUD API using Node js Express MongoDB

This tutorial is focused on Create Restful CRUD API using Node js Express MongoDB , Later on we will use these api method in our Frontend Application in Angular 6.

So lets learn how to create restful service in nodejs with express framework, and Perform Crud operations in MongoDBdata.

Prerequisites for this Application:

1) Node and Npm should be Installed in system. Following is the download Download link/instructions
https://nodejs.org/en/

2) Mongo Db should be Installed in the system. Following is the download link/instructions for it
https://www.mongodb.com/

 

Step 1) Create directory and Initialize NPM

 mkdir my_node_app
 cd my_customers
 npm init

After ‘Npm Init’ run it will ask for some meta information, Some fields (like test command) are optional you may leave blank by entering without any text.

In main script you need to provide the main bootstrap file for your application , i will provide `index.js` as main file name here.

After providing the required information it will have a composer.json file in your project like following

{
"name": "mycustomers",
"version": "1.0.0",
"description": "manage my customers",
"main": "index.js",
"scripts": {
"test": "echo \"Error: no test specified\" && exit 1"
},
"keywords": [
"manage",
"clients"
],
"author": "jeetendra",
"license": "ISC"
}

Step 2) Following dependencies we need to install in our project:

  • Express framework
  • Mongoose module to communicate with our already installed mongo server
  • Body-parser module to recieve the form data send by client applications to our api methods

Below are the commands to install above modules

npm install express --save
npm install mongoose --save
npm install body-parser --save

Step 3) Now create a index.js file to create apis in it

Now create index.js file to create API using Node js Express MongoDB

Load modules and initialize express app following code will load the modules in express app

var express = require('express');
var mongoose = require('mongoose');
var body_parser = require('body-parser');
var app = express();

After it define the database credentials using host and db name and pass that mongodb connection url in mongoose.connect method:

var db_host='localhost'
var db_name='customers_db'
mongoose.connect('mongodb://'+db_host+'/'+db_name);

After it add following 2 lines to support application/json and application/x-www-form-urlencoded type of post data in apis

// support parsing of application/json type post data
app.use(body_parser.json());
//support parsing of application/x-www-form-urlencoded post data
app.use(body_parser.urlencoded({ extended: true })); 

Step 4) Before moving further we will require to create model for our customers data

So create a folder models and create Customers.js with following code in that file (models/Customers.js)  :

var mongoose = require('mongoose');

    //code will come here to insert customer in mongo database
      var Schema = mongoose.Schema;
    // create a schema
    var CustomerSchema = new Schema({
      name: { type: String, required: true },
      phone: { type: String, required: true },
      email: { type: String, required: true },
      age: { type: String, required: true }
      
    });

   //register as model and export it with name Customers
  module.exports = mongoose.model('Customers', CustomerSchema)

Step 5) Now in our Index.js File where we already created mongo connection there , after it we put the body parser configuration.
So after that we will include the Model which we created and create the required apis for crud oprations

var Cutomer_Model = require('./models/Customers');

After it Assign a port to your application for handeling client requests using following code

var server = app.listen(8080, function () {

  console.log("Application Server Started listening requests");

});

Now we will create API using Node js Express MongoDB for Create,Read,Update,Delete Operations that will use in Angular js 6 later on
Api 1: Create Customers using POST Request:

Endpoint Name : create_customer

app.post('/create_customer', function (req, res) {
 
    var user_obj = new Cutomer_Model(req.body);

    var return_arr={};
      user_obj.save(function(err) {
      if (err)  
      {       
          return_arr.status=0;
          return_arr.message=err.message;
      }
      else
      {
        return_arr.status=1;
          return_arr.message="Customer Created Successfully";
         
      }

      var ReturnjsonString = JSON.stringify(return_arr); 

      res.json(ReturnjsonString);
      
  });


});

in above method we defined the app post method with create_customer is a endpoint name.
where we will post the data as we defined the Schema for mongo db . after it we will receive that posted data using
req.body. Now create a object for Customer model by passing the request body to its Customers Model class constructer. It will returning a customer object and using that object we are calling save method and returning the response accordingly in callback method
Api 2: Select all customers using GET Request

Endpoint Name : get_all_customers

app.get('/get_all_customers', function (req, res) {

    //select all records, just intantiate the modal with its name
 
     
    Cutomer_Model.find({}, function(err, data) {
         
        var return_arr={};

        if (err)  
        {       
            return_arr.status=0;
            return_arr.message=err.message;
        }
        else
        {
          return_arr.status=1;
            return_arr.customers=data;
           
        }

        res.json(return_arr);
 

        });
 

});

 

Api 3: Update customer using PUT Request

Endpoint Name : update_customer

app.put('/update_customer/:customer_id', function (req, res) {
 
     
    var return_arr={};
      Cutomer_Model.findByIdAndUpdate(req.params.customer_id,req.body,{new: true},function(err) {
      if (err)  
      {       
          return_arr.status=0;
          return_arr.message=err.message;
      }
      else
      {
        return_arr.status=1;
          return_arr.message="Customer Updated Successfully";
         
      }
 
      res.json(return_arr);
      
  });


});

 

Api 4: Delete customer using Delete Request

Endpoint Name : delete_customer

app.delete('/delete_customer/:customer_id', function (req, res) {
 
     
    var return_arr={};
      Cutomer_Model.findByIdAndRemove(req.params.customer_id,function(err) {
      if (err)  
      {       
          return_arr.status=0;
          return_arr.message=err.message;
      }
      else
      {
        return_arr.status=1;
          return_arr.message="Customer Deleted Successfully";
         
      }
 
      res.json(return_arr);
      
  });


});

Thanks to reading out this article focuses on Creating Resful API using Node js Express MongoDB

Apart from above scenarios there may be multiple requirements, like search with name etc fields  or get specific data with id. If you need any type of help or something not clear to you, then you may put your comments below.

Click here to download full source code for create API using Node js Express MongoDB

You are now ready to with API using Node js Express MongoDB .
Following are the Postman Screenshots to test these apis respectively

create customer api call screenshot
create customer api call screenshot

 

Get all customers api screenshot
Get all customers api screenshot

 

update customer api screenshot
update customer api screenshot

 

 

delete customer api screenshot
delete customer api screenshot

 

Images to Video making php script using FFMPEG

Hi Geeks,

This Article is based on

Images to Video making php script using FFMPEG

,  So I am providing you the complete steps to setup the FFMPEG in windows and linux environment.

FFMPEG is very good Extension for php where we can process many type of operations on audio and video like

Images to video convert ,images and audio to video ,Generate Thumbnail file from video. So I have tried it on my windows system .

Steps to install FFMPEG on windows or localhost:

Step 1: Download the Static build for windows from following page

http://ffmpeg.zeranoe.com/builds/

there will be a button for download as in the screenshotdownload_ffmpeg

 

Step 2: Install prerequisite extensions

Before making any php script please make available the GD2 Library from your php.ini by just uncommenting following lines(removing semicolons from start of these lines

;extension=php_gd.dll
;extension=php_gd2.dll

Step 3: Extract the downloaded zip and Inside Bin folder you will find ffmpeg.exe

Copy that file in your project folder in htdocs Eg: slideshow_project

Now we have all images which we need to convert into video are in any folder of this projects like Images:

there should be pattern of images name like pic1.jpg,pic2.jpg as so on…

Step 4: write and execute a command for images to video conversion, following is the command

$command1="ffmpeg -f image2 -r 1/1 -i images/pic%d.jpg -vf fps=25 test1.mp4";
//command for every 1 second image change in video
exec($command1);

above command is useful with creating a slideshow video where 2 second images will change and if you want to increase slide change duration for 3 second then you need to replace 1/1 to 1/3   from above command.

Now if you want to mix audio along with images then following command will work

$command2="ffmpeg -f image2 -r 1/5 -i images/pic%d.jpg -i audio/my_recording.mp3 -vf fps=25 test2.mp4";
//command for every 5 second image change in video along with my_recording.mp3 playing in background
exec($command2);

Assuming you have my_recording.mp3 in audio folder of project

Installing FFMPEG in linux servers by following command

sudo apt-get install ffmpeg

In that case you don’t need to follow  Step 1 and Step 3

If you are having any problem then please put your comments below , I would love to help you