CRUD operation using MEAN stack

 A blog on how to do crud operation using mean stack application from scratch

Github:https://github.com/mehulk05/Blog-using-mean

Live Demo:https://mehulk05.github.io/Blog-using-mean/

A demo of what we are creating




Let us understand what does MEAN stack means.

  • Mongo DB – It’s an open-source NoSQL cross-platform document-oriented database.
  • Express JS – It’s a web-based application framework work with Node JS, It helps to build web apps and RESTful APIs.
  • Angular 7/8/9 – It's a TypeScript based complete front-end framework developed by the Google team.
  • Node JS – It is a free JavaScript run-time environment, It executes JavaScript code outside of a browser. It is available for macOS, Windows, Linux, and Unix.

I will be using the following plugins and tools to create the MEAN Stack app.

#1 Setup Node JS development environment

Follow this link to set up Node JS in your system. Simply download and install the node as per your system bit i.e 32 and 64 bit and OS

#2 Build a Node.JS Backend

To write the manageable code, we should keep the MEAN Stack backend folder separate. Create a folder by the name of the backend or anything you like in Angular’s root directory. This folder will handle the backend code of our application, remember it will have the separate node_modules folder from Angular 7/8/9.

mkdir backend
cd backend
npm init -y

The above command will take you inside the backend folder and then generate package.json with all default configuration.

– Install and Configure required NPM packages for MEAN Stack app development

Use the below command to install the following node modules.

npm install --save body-parser cors express mongoose
  • body-parser: The body-parser npm module is a JSON parsing middleware. It helps to parse the JSON data, plain text, or a whole object.
  • CORS: This is a Node JS package, also known as the express js middleware. It allows enabling CORS with multiple options. It is available through the npm registry.
  • Express.js: Express js is a free open source Node js web application framework. It helps in creating web applications and RESTful APIs and act as middleware
  • Mongoose: Mongoose is a MongoDB ODM for Node. It allows you to interact with the MongoDB database.

Starting and stopping a server every time a change is made is a time-consuming task. To get rid of this problem we use the nodemon npm module. This package restarts the server automatically every time we make a change. We’ll be installing it locally by using the given below command.

npm install nodemon --save-dev

Also, make sure to change the package.json to start nodemon

#3 Folder Structure for Backend.




#4 Writing App.js

const path = require("path");
const express = require("express")
const mongoose = require("mongoose")
const db = require("./db/db")
const postRouter = require("./Routes/post");
const app = express();
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
extended: false
}));
app.use(cors());
const PORT = process.env.PORT || 3000app.use("/api/posts", postRouter)app.listen(PORT, (req, res) => {
console.log(`app is listening to PORT ${PORT}`)
})

#5 Writing db.js

To create the database you can go here to register and create a new database. Also, you will get the connection URL which I will be using in my code

const mongoose = require('mongoose');mongoose.Promise = global.Promise;const url = "mongodb://testuser:<password>@cluster0-shard-00-00.ecaql.mongodb.net:27017?ssl=true&replicaSet=atlas-ceza4t-shard-0&authSource=admin&retryWrites=true&w=majority"// Connect MongoDB at default port 27017.let mong = mongoose.connect(url, {
useNewUrlParser: true,
useCreateIndex: true,
useUnifiedTopology: true
}, (err) => {
if (!err) {
console.log('MongoDB Connection Succeeded.')
} else {
console.log('Error in DB connection: ' + err)
}
});

#6 Create Model with Mongoose JS

const mongoose = require('mongoose');const Post = mongoose.model('Post', {
title: {
type: String,
required: true
},
content: {
type: String,
required: true
},

});
module.exports = Post

7 Create RESTful APIs using Express JS Routes

//CREATE OPERATION

router.post("",(req, res, next) => {
        const post = new Post({
            title: req.body.title,
            content: req.body.content,
        })
        post.save().
            then(post => {
                if(post){
                    res.status(201).json({
                        message: "Post added successfully",
                        post: {
                            ...post,
                            id: post._id
                        }
                    })
                }
        }).catch(e => {
                console.log(e)
            })
    })

// READ OPERATION
router.get("/mypost", (req, res, next) => {
    Post.find({creator: req.userData.userId}).then(post => {
      if (post) {
        res.status(200).json({
            message: "Posts fetched successfully!",
            posts: post
        });
      }
    }).catch(e=>{
        console.log(e)
    });
  });

//UPDATE OPERATION
router.put(
    "/:id",
    (req, res, next) => {
        const post = new Post({
            _id: req.body.id,
            title: req.body.title,
            content: req.body.content,
         
        });
        Post.updateOne(
            { _id: req.params.id},
            post
          ).then(result => {
            if(result){
                res.status(200).json({ message: "Update successful!" });
            }       
            else {
                res.status(500).json({ message: "Error Upating Post" });
            }
        });
    }
);


//DELETE OPERATION
router.delete("/:id", (req, res, next) => {
    Post.deleteOne({ _id: req.params.id, creator: req.userData.userId }).then(
      result => {
        console.log(result);
        if (result.n > 0) {
          res.status(200).json({ message: "Deletion successful!" });
        } else {
            return res.status(401).json({ message: "Not authorized!!" });
        }
      }
    );
  });

# 8 Creating Frontend

NOw moving to the frontend side we will get our data in the service file. Skipping the installation lets have 2 component with

  1. PostCreate component
  2. PostList Component
  3. Post Service

#9 Creating Post Service

const BACKEND_URL = "http://localhost:3000/api"

addPost(title: string, content: string) {
    const postData = new FormData();
    postData.append("title", title);
    postData.append("content", content);
   
    this.http
      .post<{ message: string; post: Post }>(
        BACKEND_URL,
        postData
      )
      .subscribe(responseData => {
        this.router.navigate(["/"]);
      }),
      err => {   
        console.log(err)
      }
  }
 getPosts() {
    this.http.get<{ message: string; posts: any }>(BACKEND_URL)
      .pipe(
        map(postData => {
          return postData.posts.map(post => {
            return {
              title: post.title,
              content: post.content,
              id: post._id,
            };
          });
        })
      )
      .subscribe(transformedPosts => {
        console.log(transformedPosts)
      },
        err => {
          console.log(err)
        });
  }        
        
 getPost(id: string) {
    return this.http.get<{
      _id: string, title: string, content: string, imagePath: string,
      creator: string;
    }>(
      BACKEND_URL +"/" + id
    );
  }

        
updatePost(id: string, title: string, content: string) {
    let postData: Post | FormData;
      postData = new FormData();
      postData.append("id", id);
      postData.append("title", title);
      postData.append("content", content);
    }
    this.http
      .put(BACKEND_URL + "/" +id, postData)
      .subscribe(response => {
        this.router.navigate(["/"]);
      },
        err => {
         
        });
  }
        
 deletePost(postId: string) {
    this.http
      .delete(BACKEND_URL +"/"+ postId)
      .subscribe((data) => {
        this.router.navigate(["/"]);
      },
        e => {
          console.log(e)
        });
  }

# 10 Creating Component(Post create component)

To create a post we will use Angular service and RESTful APIs. I’ve used Reactive Forms to register an employee. We are also covering Reactive forms validations in our MEAN Stack app tutorial.

#10.1 Post-create.component.html

<form [formGroup]="form" (submit)="onSavePost()">
    <div class="form-group">
      <input
        type="text"
        formControlName="title"
        class="form-control"
        placeholder="Post Title"
      />
      <span
        class="text-danger"
        *ngIf="form.get('title').invalid && form.get('title').touched"
        >Please enter a post title.</span
      >
    </div>
    
    <div class="form-group">
      <textarea
        class="form-control"
        rows="4"
        formControlName="content"
        placeholder="Post Content"
      ></textarea>
      <span
        class="text-danger"
        *ngIf="form.get('content').invalid && form.get('content').touched"
        >Please enter a post title.</span
      >
    </div>
    <button class="btn btn-primary" [disabled]="form.invalid" type="submit">
      Save Post
    </button>
  </form>

#10.2 Createpost.component.ts

form: FormGroup;

 constructor(
    private ps: PostService,
    public route: ActivatedRoute
  ) { }

ngOnInit(): void {
 this.createForm()
 }

createForm() {
    this.form = new FormGroup({
      title: new FormControl(null, {
        validators: [Validators.required, Validators.minLength(3)]
      }),
      content: new FormControl(null, { validators: [Validators.required] }),
      })
    });
  }

onSavePost() {
    if (this.form.invalid) {
      return;
    }
 this.ps.addPost( this.form.value.title,  this.form.value.content );
 this.form.reset();
}

# 11 Show Post List and Delete Post Object using RESTful API in MEAN Stack App

Here we will fetch all the posts with their content. Also, we will perform our delete operation here where we have provided one button where when we click on it, the post will be deleted.

#11.1 Postlist.component.html

 <div class="card row card-featured"   *ngFor="let post of posts;let i=index">
     <h3 class="font-weight-dark">
        <a [routerLink]="[post.id]"> {{ post.title }}</a>
     </h3>
   
    <div class="desc">
       <p>{{post.content |slice:0: 170 }}
        <a [routerLink]="[post.id]">{{post.content.length > 170 ? '...Read More' : ''}}</a></p>
  </div>
   
    <span class="delete" (click)="removePost(post.id)">
       <button type="button" class="btn btn-danger btn-sm">Delete</button>
   </span>
</div>

#11.2 PostList.component.ts
posts: Post[] = [];

constructor(private ps: PostService) { }

 ngOnInit(): void {
  this.ps.getPosts().subscirbe(post=>{
  this.posts=post.post  
})
}

 removePost(postId: string) {
    this.postsService.deletePost(postId);
 }

#12 Edit Post Data in Mean Stack

In order to edit post data, we need to add the following code in our createPost component which we will reuse for editing the data also. Also, note that HTML mark up will be the same for edit posts also. So I am skipping that part.

#12.1 CreatePost.component.ts(for editing)

form: FormGroup;
post: Post;
private mode = "create";
private postId: string;

ngOnInit(): void {
    this.route.paramMap.subscribe((paramMap: ParamMap) => {
      if (paramMap.has("postId")) {
        this.mode = "edit";
        this.postId = paramMap.get("postId");
        this.getPostById(this.postId)
      }
      else {
        this.mode = "create";
        this.postId = null;

      }
    })
    this.createForm()
  }

 getPostById(id) {
    this.isLoading=true
    this.ps.getPost(id).subscribe(postData => {
    
      this.post = {
        id: postData._id,
        title: postData.title,
        content: postData.content,
      };

      console.log(postData)
      this.form.setValue({
        title: this.post.title,
        content: this.post.content,
        
      });
      this.isLoading = false;
    });
  }
  
   createForm() {
    this.form = new FormGroup({
      title: new FormControl(null, {
        validators: [Validators.required, Validators.minLength(3)]
      }),
      content: new FormControl(null, { validators: [Validators.required] }),
    });
  }
  
 onSavePost() {
    this.postdate = new Date()
    console.log(this.postdate)
    if (this.form.invalid) {
      return;
    }
    this.isLoading = true;
    console.log(this.form.value)
    if (this.mode === "create") {
      console.log("inside")
      this.ps.addPost(
        this.form.value.title,
        this.form.value.content,
      );
    }
    else {
      this.ps.updatePost(
        this.postId,
        this.form.value.title,
        this.form.value.content,
      );
    }
    this.form.reset();
  }
}

We have created a basic MEAN Stack Angular 7 CRUD app, now enter the below command to start your project on the browser.

ng serve

Demo

Image for post
Create post
Image for post
Post List

Conclusion

Finally, we are done with this MEAN Stack Tutorial using Angular 9/8/7 and Bootstrap 4. I have tried to highlight every essential topic in this tutorial. However, if you have skipped anything you can check out my Github Repo




Comments

Popular posts from this blog

Blog App Using MERN Stack

Read data from Google spreadsheet in Angular

Authentication in MERN Stack Using JWT