Hướng dẫn thêm mới sản phẩm (có upload file) trong angular vs API NodeJs

2023-07-10 11:25:22

Hướng dẫn thêm mới sản phẩm (có upload file) trong angular vs API NodeJs, Hướng dẫn upload file angular,

Phần 1 Xây dụng API Nodejs:

Bước 1: Chuẩn bị database:

CREATE DATABASE `demo_btl` DEFAULT CHARACTER SET utf8 COLLATE utf8_unicode_ci;

CREATE TABLE IF NOT EXISTS `categories` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255),
PRIMARY KEY `pk_id`(`id`)
) ENGINE = InnoDB;

CREATE TABLE IF NOT EXISTS `products` (
`id` INT UNSIGNED NOT NULL AUTO_INCREMENT,
`name` VARCHAR(255),
`price` FLOAT NOT NULL,
`image` VARCHAR(255),
`category_id` INT UNSIGNED,
PRIMARY KEY `pk_id`(`id`)
) ENGINE = InnoDB;

ALTER TABLE `products`
ADD CONSTRAINT `fk_the_pro_far_cate`
FOREIGN KEY (`category_id`)
REFERENCES `categories` (`id`)
ON DELETE NO ACTION
ON UPDATE CASCADE

Bước 2 Xây dựng API NodeJS:

(ở phần này mình không hướng dẫn cụ thể từng bước các bạn có thể tham khảo link sau : Hướng dẫn)

const express = require('express');
const app = express();
const bodyParser = require('body-parser');
const conn = require('./db/connect');
const cors = require('cors');
const uploadFile = require('./util/fileUpload');
app.use(bodyParser.json());

app.use(express.static('public/uploads'));

app.use(cors({
origin: '*'
}));


app.post('/api/product',uploadFile.single('image'),(req,res)=>{
let fileName = req.protocol+'://'+req.get('host')+'/'+req.file.filename;
// console.log(req.body);
let sql = `INSERT INTO products (name,price,image,category_id) VALUES ('${req.body.name}',${req.body.price},'${fileName}',${req.body.category_id})`;
conn.query(sql,(err,data)=>{
if(err)
{
console.log(err);
res.sendStatus(500)
} else{
res.json(data);
}
})
})

app.get('/api/products',(req,res)=>{
conn.query("SELECT products.*,categories.name as 'category' FROM products JOIN categories ON products.category_id = categories.id",(err,data)=>{
if(err)
{
console.log(err);
res.sendStatus(500)
} else{
res.json(data);
}
})
});

app.get('/api/product/:id',(req,res)=>{
let id = req.params.id;
conn.query(`SELECT * FROM products WHERE id = ${id}`,(err,data)=>{
if(err)
{
res.sendStatus(500)
} else{
res.json(data[0]);
}
})
})
app.listen(3000,()=>{
console.log("ok");
})

code phần sử lý upfile:

const multer = require('multer');

const storage = multer.diskStorage({
destination: (req,file,callback)=>{
callback(null,'./public/uploads');
},
filename: (req,file,callback)=>{
callback(null,file.originalname);
} 
});
const uploadFile = multer({storage:storage});

module.exports = uploadFile;

Phần 2 xây dựng ứng dụng angular phần quản lý sản phẩm :

Bước 1: Tạo product service như sau:

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';
const urlAPI = 'http://localhost:3000/api/products';
@Injectable({
providedIn: 'root'
})
export class ProductService {

constructor(private httpClient:HttpClient) { }
geAll():Observable<any>{
return this.httpClient.get(urlAPI);
}

add(product:any):Observable<any>{
return this.httpClient.post('http://localhost:3000/api/product',product);
}
}

Tạo categoryservice như sau:

import { HttpClient } from '@angular/common/http';
import { Injectable } from '@angular/core';
import { Observable } from 'rxjs';

const urlAPI = 'http://localhost:3000/api/categories';
@Injectable({
providedIn: 'root'
})
export class CategoryService {

constructor(private httpClient:HttpClient) { }

geAll():Observable<any>{
return this.httpClient.get(urlAPI);
}
} 

Bước 2 : Tạo component sử dụng trong demo

Bài hôm nay mình tạo 2 component 1 để hiển thị danh sách, 1 để chứa form thêm mới sản phẩm kèm upload ảnh >

Tạo component hiển thị danh sách sản phẩm : như sau:

file product.component.ts:

import { Component } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { CategoryService } from 'src/app/services/category.service';
import { ProductService } from 'src/app/services/product.service';

@Component({
selector: 'app-product',
templateUrl: './product.component.html',
styleUrls: ['./product.component.css']
})
export class ProductComponent {
listProduct:any;

constructor(private productSerive:ProductService,private categoryService:CategoryService){}
ngOnInit(): void {
this.getList();
}

getList(){
this.productSerive.geAll().subscribe((data)=>{
this.listProduct = data;
})
}

}

file product.component.html:

<div class="row">
<div class="col-lg-8 mt-5">
<a class="btn btn-success"[routerLink]="['add-product']">Add new </a>
<table class="table">
<thead>
<tr>
<th>STT</th>
<th>Name</th>
<th>Image</th>
<th>Category</th>
</tr>
</thead>
<tbody>
<tr *ngFor="let item of listProduct;let i = index">
<td scope="row">{{i+1}}</td>
<td>{{item.name}}</td>
<td><img [src]="item.image" width="100px"/></td>
<td>{{item.category}}</td>
</tr>
</tbody>
</table>
</div>
</div>

Tạo component thêm mới sản phẩm:

File add-product.component.ts:

import { Component } from '@angular/core';
import { FormControl, FormGroup } from '@angular/forms';
import { Router } from '@angular/router';
import { CategoryService } from 'src/app/services/category.service';
import { ProductService } from 'src/app/services/product.service';

@Component({
selector: 'app-add-product',
templateUrl: './add-product.component.html',
styleUrls: ['./add-product.component.css']
})

export class AddProductComponent {
listCategory:any;
file:any;
preview:any;
profileForm = new FormGroup({
name: new FormControl(''),
price: new FormControl(''),
category_id: new FormControl('')
});
constructor(private productSerive:ProductService,private categoryService:CategoryService,private router: Router){}

ngOnInit(): void {
this.getCategories();
}
getCategories(){
this.categoryService.geAll().subscribe((data)=>{
this.listCategory = data;
})
}
addForm(){
console.log(this.profileForm.value);
let name:any = this.profileForm.value.name;
let price:any = this.profileForm.value.price;
let category_id:any = this.profileForm.value.category_id;
if(this.file){
const formData = new FormData();
formData.append('image',this.file,this.file.name);
formData.append('name',name);
formData.append('price',price);
formData.append('category_id',category_id);
this.productSerive.add(formData).subscribe(data=>{
if(data){
this.router.navigate(["admin/product"]);
}
})
}
}

uploadFile(event:any){
this.file = event.target.files[0];
const reader = new FileReader();
reader.readAsDataURL(this.file)
reader.onload = (e:any)=>{
this.preview = e.target.result; 
}
}
}

File add-product.component.html:

<div class="row">
<div class="col-lg-6">
<form [formGroup]="profileForm" (submit)="addForm()">
<div class="form-group">
<label for="exampleInputEmail1">Product Name</label>
<input type="text" class="form-control" formControlName="name">
</div>
<div class="form-group">
<label for="exampleInputEmail1">Price</label>
<input type="text" class="form-control" formControlName="price">
</div>
<div class="form-group">
<label for="exampleInputEmail1">Category</label>
<select class="form-control" formControlName="category_id" id="">
<option value="">---Chon danh muc ---</option>
<option *ngFor="let item of listCategory" value="{{item.id}}">{{item.name}}</option>
</select>
</div>
<div class="form-group">
<label for="exampleInputEmail1">Image</label>
<input type="file" class="form-control" (change)="uploadFile($event)" enctype="multipart/form-data">
<img [src]="preview" class="w-100" />
</div>
<button type="submit" class="btn btn-primary">Thêm mơi</button>
</form>
</div>
</div>

Định nghĩa route tương ứng:

const routes: Routes = [
{path:'',component:MasterviewadminComponent,children:[
{path:'category',component:CategoryComponent},
{path:'product',component:ProductComponent},
{path:'add-product',component:AddProductComponent}
]}
];