Close Menu
Soshace Digital Blog

    Subscribe to Updates

    Get The Latest News, Updates, And Amazing Offers

    What's Hot
    React Native

    Building a Realtime Messaging app with React Native and Firebase

    Programming

    RxJS Introduction

    Entrepreneurship

    Leveraging Crowdfunding: A Strategic Guide for Startups

    Important Pages:
    • Home
    • About
    • Services
    • Contact Us
    • Privacy Policy
    • Terms & Conditions
    Facebook X (Twitter) Instagram LinkedIn YouTube
    Today's Picks:
    • Scaling Success: Monitoring Indexation of Programmatic SEO Content
    • Leveraging Influencers: Key Drivers in New Product Launches
    • How Privacy-First Marketing Will Transform the Industry Landscape
    • The Impact of Social Proof on Thought Leadership Marketing
    • Balancing Value-Driven Content and Promotional Messaging Strategies
    • Top Influencer Marketing Platforms to Explore in 2025
    • Emerging Trends in Marketing Automation and AI Tools for 2023
    • Strategies to Mitigate Duplicate Content in Programmatic SEO
    Sunday, September 28
    Facebook X (Twitter) Instagram LinkedIn YouTube
    Soshace Digital Blog
    • Home
    • About
    • Services
    • Contact Us
    • Privacy Policy
    • Terms & Conditions
    Services
    • SaaS & Tech

      Maximizing Efficiency: How SaaS Lowers IT Infrastructure Costs

      August 27, 2025

      Navigating Tomorrow: Innovations Shaping the Future of SaaS

      August 27, 2025

      Maximizing Impact: Strategies for SaaS & Technology Marketing

      August 27, 2025
    • AI & Automation

      Enhancing Customer Feedback Analysis Through AI Innovations

      August 27, 2025

      Navigating the Impact of AI on SEO and Search Rankings

      August 27, 2025

      5 Automation Hacks Every Home Service Business Needs to Know

      May 3, 2025
    • Finance & Fintech

      Critical Missteps in Finance Marketing: What to Avoid

      August 27, 2025

      Analyzing Future Fintech Marketing Trends: Insights Ahead

      August 27, 2025

      Navigating the Complex Landscape of Finance and Fintech Marketing

      August 27, 2025
    • Legal & Compliance

      Exploring Thought Leadership’s Impact on Legal Marketing

      August 27, 2025

      Maximizing LinkedIn: Strategies for Legal and Compliance Marketing

      August 27, 2025

      Why Transparency Matters in Legal Advertising Practices

      August 27, 2025
    • Medical Marketing

      Enhancing Online Reputation Management in Hospitals: A Guide

      August 27, 2025

      Analyzing Emerging Trends in Health and Medical Marketing

      August 27, 2025

      Exploring Innovative Content Ideas for Wellness Blogs and Clinics

      August 27, 2025
    • E-commerce & Retail

      Strategic Seasonal Campaign Concepts for Online and Retail Markets

      August 27, 2025

      Emerging Trends in E-commerce and Retail Marketing Strategies

      August 27, 2025

      Maximizing Revenue: The Advantages of Affiliate Marketing for E-Commerce

      August 27, 2025
    • Influencer & Community

      Leveraging Influencers: Key Drivers in New Product Launches

      August 27, 2025

      Top Influencer Marketing Platforms to Explore in 2025

      August 27, 2025

      Key Strategies for Successful Influencer Partnership Negotiations

      August 27, 2025
    • Content & Leadership

      The Impact of Social Proof on Thought Leadership Marketing

      August 27, 2025

      Balancing Value-Driven Content and Promotional Messaging Strategies

      August 27, 2025

      Analyzing Storytelling’s Impact on Content Marketing Effectiveness

      August 27, 2025
    • SEO & Analytics

      Scaling Success: Monitoring Indexation of Programmatic SEO Content

      August 27, 2025

      Strategies to Mitigate Duplicate Content in Programmatic SEO

      August 27, 2025

      Effective Data Visualization Techniques for SEO Reporting

      August 27, 2025
    • Marketing Trends

      How Privacy-First Marketing Will Transform the Industry Landscape

      August 27, 2025

      Emerging Trends in Marketing Automation and AI Tools for 2023

      August 27, 2025

      Maximizing ROI: Key Trends in Paid Social Advertising

      August 27, 2025
    Soshace Digital Blog
    Blog / JavaScript / POS Tutorial / Create simple POS with React.js, Node.js, and MongoDB #11: CRUD with Relation
    POS Tutorial

    Create simple POS with React.js, Node.js, and MongoDB #11: CRUD with Relation

    Krissanawat KaewsanmuangBy Krissanawat KaewsanmuangAugust 5, 2020No Comments11 Mins Read
    Facebook Twitter Pinterest Telegram LinkedIn Tumblr Email Reddit
    Create simple POS with React.js, Node.js, and MongoDB #11: CRUD with Relation
    Create simple POS with React.js, Node.js, and MongoDB #11: CRUD with Relation
    Share
    Facebook Twitter LinkedIn Pinterest Email Copy Link
    Create simple POS with React.js, Node.js, and MongoDB #11: CRUD with Relation

    Defenition: POS – “Point of Sale”. At the point of sale, the merchant calculates the amount owed by the customer, indicates that amount, may prepare an invoice for the customer (which may be a cash register printout), and indicates the options for the customer to make payment.

    In the previous chapter, we successfully implemented CRUD operation for the supplier information of a grocery store. In this chapter, we are going to continue to implement CRUD operation for the Relation data and assign the POS machine to branch.

    The key is to discover how to make relations on the database and deal with new UI change by adding multiple dropdowns. And lastly, display POS machine data in the branch index page.

    Let’s get started!

    First, we are going to start on the branch and POS machine.

    Let us derive a relation from real-life for better understanding. We cannot place one machine to multiple branches but we can place multiple POS machines in the same branch as depicted in the diagram below:

    Branch and POS relation diagram
    Branch and POS relation diagram

    Hence, we can define one too many relations.

    Next, we move on to the coding implementations.

    Updating Schema

    Here, we are going to start from the backend by updating the database schema. We are going to add a relation between the POS machine schema in Branch schema. For that, we need to open the file branch.schema.js and add the code provided in the following code snippet:

    const mongoose = require("mongoose");
    const schema = mongoose.Schema({
        name: String,
        address: String,
        tel: String,
        frontimage: String,
        pos_machines: [
            { type: mongoose.Schema.Types.ObjectId, ref: 'pos_machines'    }
        ],
        created: { type: Date, default: Date.now },
    });
    
    module.exports = mongoose.model("branch", schema);

    Next, we will start the update function from frontend to backend.

    Create operation

    In order to add the POS machine data to the branch, we are going to use the most popular dropdown component name React Select.

    In frontend React project, we need to install this component first by running the following command in the project terminal:

    yarn add react-select

    In components/branch/create.js, we need to import the Select component from react-select package as shown in the code snippet below:

    import Select from 'react-select'

    Then, we will add it to somewhere on the form dropdown which will enable multiple selection following our first diagram. Next, we use the local state multiselect in order to handle the select options.

    For the special part, we are going to create a new constant to handle options data separately from normal constant as shown in the code snippet below:

    <Select
            value={multiselect}
            onChange={setMultiselect}
            isMulti
            closeMenuOnSelect={false}
            options={branchReducer.options
                    ? branchReducer.options : null}
    />

    Now, we add a new constant as shown in the code snippet below:

    export const FETCHOPTION_SUCCESS = "FETCHOPTION_SUCCESS";

    Then, we need to import the new constant to the branch reducer. Here, we are going to create a case like fetching data successfully but change index name to options in order to avoid the same data in the index page. For that, we need to use the code from the following code snippet:

    import {
        BRANCH_FETCHING,
        BRANCH_SUCCESS,
        BRANCH_FAILED,
        BRANCH_CLEAR,
        FETCHOPTION_SUCCESS
    } from "../constants";
    
    ...............
    
    export default (state = initialState, { type, payload }) => {
        switch (type) {
          .................
            case FETCHOPTION_SUCCESS:
                return { ...state, isFetching: false, isError: false, options: payload };
            default:
                return state;
        }
    };

    Now in the branch.action.js file, we need to import new constant as shown in the code snippet below:

    import {
        BRANCH_FETCHING,
        BRANCH_SUCCESS,
        BRANCH_FAILED,
        BRANCH_CLEAR, FETCHOPTION_SUCCESS
    } from "../constants";

    Then, we need to create a function to dispatch new event and pass options to state as shown in the code snippet below:

    export const setFetchOptionStateToSuccess = (payload) => ({
        type: FETCHOPTION_SUCCESS,
        payload,
    });

    In order to use this, we need to create a new action for fetching POS machine data. After successful fetching, we need to clean data in order to match on react select as shown in the code snippet below:

    export const getDropdownPOS = () => {
        return async (dispatch) => {
            dispatch(setBranchStateToFetching());
            const response = await httpClient.get(
                process.env.REACT_APP_API_URL + "branch_getpos"
            );
            if (response.data.result == "success") {
                let result = response.data.data.flat().map(item => {
                    return {
                        value: item._id,
                        label: item.alias
                    };
                })
    
                dispatch(setFetchOptionStateToSuccess(result));
            } else if (response.data.result === "error") {
                dispatch(setBranchStateToFailed());
                swal("Error!", response.data.message, "error");
            }
        };
    };

    Then, we will observe that we dispatched a new event and assign option data.

    Read More:  Working with Jotai as your next state management in React

    For backend, we need to create a new endpoint in api_branch.js. We must not forget to import the pos_machine schema file at the beginning.

    By using the query in the code snippet below, we are going to select all of the data from the tables based on alias and column id:

    router.get("/branch_getpos", async (req, res) => {
      try {
        let data = await posmachine.find({}).select({ "alias": 1, "_id": 1 }).sort({ created: -1 });
        res.json({
          result: "success",
          message: "Fetch Single Branch Successfully",
          data: data,
        });
      } catch (err) {
        console.log(err)
        res.json({ result: "error", message: err.msg });
      }
    });

    We have completed our backend configurations here. Now, we move to the front end to create the Component for it.

    We need to dispatch a new action using useEffect in the create component as shown in the code snippet below:

    useEffect(() => {
            dispatch(branchActions.getDropdownPOS())
    }, []);

    Hence, we have the dropdown component from the server as we can see in the screenshot below:

    Dropdown from database
    Dropdown from database

    We are not done yet.

    Next, we are going to save data with relation. We start by attaching new select data to formData. But before attaching, we need to clean data again by using the map function in order to keep id only as shown in the code snippet below:

          onSubmit={(values, { setSubmitting }) => {
                      let formData = new FormData();
                      formData.append("name", values.name);
                      formData.append("tel", values.tel);
                      formData.append("address", values.address);
                      let result = multiselect.map(arr => arr.value)
    
                      formData.append("pos_machines", result)
                      if(values.frontimage) {
                       formData.append("frontimage", values.frontimage);
                      }
            dispatch(branchActions.Create(formData, props.history));
                        setSubmitting(false);
         }}

    On the backend, we start to update the create endpoint. Instead of throwing a request object to mongoose, we start to assign for an individual column.

    Next, the POS machine-id that we get from the client is the plain text format. Hence, we need to split it and convert it into an array.

    Then after creating a new branch, we query POS machine data and assign it to a branch object and update query again as directed in the code snippet below:

    router.post("/branch", async (req, res) => {
      // console.log(req)
      try {
        var form = new formidable.IncomingForm();
    
        form.parse(req, async (err, fields, files) => {
    
          let newBranch = await branch.create({ name: fields.name, tel: fields.tel, address: fields.address });
          await uploadImage(files, newBranch);
    
          let pos_arr = fields.pos_machines.split(',')
          const pos = await posmachine.find().where('_id').in(pos_arr).exec();
          newBranch.pos_machines = pos
          await newBranch.save()
          res.json({ result: "success", message: "Create Brach data successfully" });
        });
      } catch (err) {
        res.json({ result: "error", message: err.msg });
      }
    });

    Hence, we are have successfully completed the Create operation.

    Index Operation

    After the Create operation is successful, we are going to redirect to the index page. Hence, we need to update the index page endpoint with a query for POS machine data.

    Here, we use populate method to grab related data and send the response back to the client as shown in the code snippet below:

    router.get("/branch", async (req, res) => {
      try {
        await branch.find({}).populate('pos_machines').exec(function (err, data) {
          if (err) {
            console.log(err);
          } else {
            res.json({
              result: "success",
              message: "Fetch Branch Successfully",
              data: data,
            });
          }
        });
      } catch (err) {
        res.json({ result: "error", message: err.msg });
      }
    });

    Now, we come back to the front end. We don’t need to do anything special in front end part now. We just need to create a new column in order to display POS alias and start iterating the data using map function as shown in the code snippet below:

    <td>{data.name}</td>
     <td>{data.address}</td>
     <td>
        {data.pos_machines.map(value => {
          return value.alias + "," })
         }
    </td>
     <td>{data.created}</td>

    Hence, we can see create and index operations in action in the following simulation:

    Show realation POS data on index
    Show realation POS data on index

    Our Index operation completes here. Now, we move on to the update operation.

    Update Operation

    For the update operation, we want to populate dropdown first. After that, we need to make the second request for populating another form in order to make the data selected.

    Read More:  React and AJAX - The Art of Fetching Data in React

    The first network request is to populate the dropdown that we have created on Create operation.

    The second request will mark the data as selected on the dropdown.

    One interesting thing here is that we need to completely populate dropdown until we mark selected. We use then promise method to wait for the first request to complete before firing the second action as shown in the code snippet below:

    export const getSingleBranch = (id) => {
        return async (dispatch) => {
            dispatch(setBranchStateToFetching());
            const response = await httpClient.get(
                process.env.REACT_APP_API_URL + "branch/" + id
            );
    
            if (response.data.result == "success") {
                dispatch(getDropdownPOS()).then(() => {
                    dispatch(setBranchStateToSuccess(response.data.data));
                })
    
            } else if (response.data.result === "error") {
                dispatch(setBranchStateToFailed());
                swal("Error!", response.data.message, "error");
            }
        };
    };

     

    For backend, we need to update the mongoose query to populate relation document as shown in the code snippet below:

    router.get("/branch/:id", async (req, res) => {
      try {
        await branch.findById({ _id: req.params.id })
          .populate('pos_machines').exec(function (err, data) {
            if (err) {
              console.log(err);
            } else {
              res.json({
                result: "success",
                message: "Fetch Single Branch Successfully",
                data: data,
              });
            }
          });
      } catch (err) {
        res.json({ result: "error", message: err.msg });
      }
    });

    The complicated task is not resolved yet. In UI, we need to wait until everything is done and marked selected.

    In react-select, they provide us with the parameter named defaultValue to mark initial select but they did not provide any method to set defaultValue after page loading completes.

    In order to resolve this, we need to hold on and wait until every server request has successfully loaded.

    Then, we need to create separate render function as shown in the code snippet below:

    const renderSelectwithSelected = () => {
            {
                if (branchReducer.result) {
                    return (
                        <div class="form-group ">
                            <Select
                                name="pos_machines"
                                defaultValue={branchReducer.result
                                    ? branchReducer.result.pos_machines.map(val => {
                                        return {
                                            'value': val._id,
                                            'label': val.alias
                                        }
                                    }) : null}
                                // onChange={setMultiselect}
                                isMulti
                                closeMenuOnSelect={false}
                                options={branchReducer.options
                                    ? branchReducer.options : null}
                            />
                        </div>
    
                    )
                } else {
                    return null; // or loading graphic
                }
            }
        }

    Then, we need to attach it to the UI as shown in the code snippet below:

    {renderSelectwithSelected()}
        <div class="form-group ">
            {showPreviewImage(values)}
        </div>

    Hence, if we test it out, we will get the result as demonstrated in the following simulation:

    Populate POS dropdown
    Populate POS dropdown

    Updating Data

    In order to update the data on update operation, we need to perform some configurations in the on create operation.

    First, we need to assign the selected option to formData by assigning it to the state.

    Here, we are going to create a new state called multi-select using useState hook as shown in the code snippet below:

    const [multiselect, setMultiselect] = useState([])

    Then, we need to assign it to Select component as shown in the code snippet below:

     <Select
       name="pos_machines"
       onChange={setMultiselect}

    And then, assign it to formData as shown in the code snippet below:

    let result = multiselect.map(arr => arr.value)
    formData.append("pos_machines", result)

    On the backend, we just need to update the following create operation:

    router.put("/branch", async (req, res) => {
    
      try {
        var form = new formidable.IncomingForm();
    
        form.parse(req, async (err, fields, files) => {
          let updateBranch = await branch.findByIdAndUpdate({ _id: fields.id }, { name: fields.name, tel: fields.tel, address: fields.address });
          let pos_arr = fields.pos_machines.split(',')
          const pos = await posmachine.find().where('_id').in(pos_arr).exec();
          updateBranch.pos_machines = pos
          await updateBranch.save()
          await uploadImage(files, updateBranch);
          res.json({ result: "success", message: "Update Brach data successfully" });
        });
      } catch (err) {
        res.json({ result: "error", message: err.msg });
      }
    });

     

    Hence, we will get the result as shown in the following simulation:

    Update success
    Update success

    Delete Operation

    The delete operation here is no different from the previous chapter. We do not need to make any updates to it.

    Finally, we have successfully completed the CRUD operation with Relation data.

    Conclusion

    In this chapter, we learned a lot about MongoDB relations. We also learned how to update our UI to support relation data. We got guidance on how to use Select component from the react-select package as well.

    In the next chapter, we will upgrade our table by integrating react-table package configurations.

    Do not miss the codes for this chapter that are available on Github for both Frontend and Backend.

     

    Share. Facebook Twitter Pinterest LinkedIn Tumblr Email
    Krissanawat Kaewsanmuang
    • Website
    • X (Twitter)

    Developer Relation @instamobile.io

    Related Posts

    JAMstack Architecture with Next.js

    March 15, 2024

    Rendering Patterns: Static and Dynamic Rendering in Nextjs

    March 7, 2024

    Handling Mutations and Data Fetching Using React Query

    September 12, 2023
    Leave A Reply Cancel Reply

    You must be logged in to post a comment.

    Stay In Touch
    • Facebook
    • Twitter
    • Pinterest
    • Instagram
    • YouTube
    • Vimeo
    Don't Miss
    B2B Leads December 19, 2024

    Effective Strategies for Targeting B2B Lead Generation Audiences

    Targeting B2B lead generation effectively requires a mix of strategic approaches. Focus on defining your ideal customer profile, utilizing data-driven insights, and leveraging social media platforms to connect with decision-makers in your industry.

    Creating Real-Time API with Beautiful Soup and Django REST Framework

    February 26, 2020

    An In-Depth Guide to Algorithms and Data Structures

    November 26, 2024

    Oksana Trypolska: I Don’t Know Any Person Who, After Working Remotely, Returned to the Office

    August 1, 2019

    Categories

    • AI & Automation
    • Angular
    • ASP.NET
    • AWS
    • B2B Leads
    • Beginners
    • Blogs
    • Business Growth
    • Case Studies
    • Comics
    • Consultation
    • Content & Leadership
    • CSS
    • Development
    • Django
    • E-commerce & Retail
    • Entrepreneurs
    • Entrepreneurship
    • Events
    • Express.js
    • Facebook Ads
    • Finance & Fintech
    • Flask
    • Flutter
    • Franchising
    • Funnel Strategy
    • Git
    • GraphQL
    • Home Services Marketing
    • Influencer & Community
    • Interview
    • Java
    • Java Spring
    • JavaScript
    • Job
    • Laravel
    • Lead Generation
    • Legal & Compliance
    • LinkedIn
    • Machine Learning
    • Marketing Trends
    • Medical Marketing
    • MSP Lead Generation
    • MSP Marketing
    • NestJS
    • Next.js
    • Node.js
    • Node.js Lessons
    • Paid Advertising
    • PHP
    • Podcasts
    • POS Tutorial
    • Programming
    • Programming
    • Python
    • React
    • React Lessons
    • React Native
    • React Native Lessons
    • Recruitment
    • Remote Job
    • SaaS & Tech
    • SEO & Analytics
    • Soshace
    • Startups
    • Swarm Intelligence
    • Tips
    • Trends
    • Vue
    • Wiki
    • WordPress
    Top Posts

    Effective Strategies for Managing Project Dependencies

    JavaScript November 24, 2024

    How to pay your foreign remote workers?

    JavaScript October 9, 2018

    Python Array Explained and Visualized

    Programming October 29, 2019

    How To Build a Github Jobs App using React, Apollo, and GraphQL – Part #1: Build the GraphQL Server

    GraphQL September 28, 2020

    Subscribe to Updates

    Get The Latest News, Updates, And Amazing Offers

    About Us
    About Us

    Soshace Digital delivers comprehensive web design and development solutions tailored to your business objectives. Your website will be meticulously designed and developed by our team of seasoned professionals, who combine creative expertise with technical excellence to transform your vision into a high-impact, user-centric digital experience that elevates your brand and drives measurable results.

    7901 4th St N, Suite 28690
    Saint Petersburg, FL 33702-4305
    Phone: 1(877)SOSHACE

    Facebook X (Twitter) Instagram Pinterest YouTube LinkedIn
    Our Picks
    JavaScript

    Build Real-World React Native App #9 : Implementing Remove Ads Feature

    CSS

    Imperative Guide to CSS masking

    JavaScript

    Top 11 Django Interview Questions

    Most Popular

    Guide to HR adviser and Clients lessening

    Franchising

    Create simple POS with React.js, Node.js, and MongoDB #12 : Getting started with React Table

    Node.js

    Overview of FREE Python Programming Courses for Beginners

    Beginners
    © 2025 Soshace Digital.
    • Home
    • About
    • Services
    • Contact Us
    • Privacy Policy
    • Terms & Conditions

    Type above and press Enter to search. Press Esc to cancel.