{"id":26368486,"url":"https://github.com/asphub/ng5appex","last_synced_at":"2026-04-07T23:31:16.633Z","repository":{"id":43447357,"uuid":"124388130","full_name":"asphub/ng5AppEx","owner":"asphub","description":"Angular 5 + Material Sample Application","archived":false,"fork":false,"pushed_at":"2022-12-29T10:20:26.000Z","size":3656,"stargazers_count":1,"open_issues_count":9,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-03-16T22:42:03.845Z","etag":null,"topics":["angular","cli","css","database","material","mongodb","navigation","scss"],"latest_commit_sha":null,"homepage":"https://asphub.github.io/ng5AppEx/","language":"CSS","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/asphub.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-03-08T12:27:55.000Z","updated_at":"2020-03-04T04:54:55.000Z","dependencies_parsed_at":"2023-01-31T08:45:35.721Z","dependency_job_id":null,"html_url":"https://github.com/asphub/ng5AppEx","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/asphub/ng5AppEx","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asphub%2Fng5AppEx","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asphub%2Fng5AppEx/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asphub%2Fng5AppEx/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asphub%2Fng5AppEx/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/asphub","download_url":"https://codeload.github.com/asphub/ng5AppEx/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/asphub%2Fng5AppEx/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31533823,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-07T16:28:08.000Z","status":"ssl_error","status_checked_at":"2026-04-07T16:28:06.951Z","response_time":105,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["angular","cli","css","database","material","mongodb","navigation","scss"],"created_at":"2025-03-16T22:39:30.527Z","updated_at":"2026-04-07T23:31:16.612Z","avatar_url":"https://github.com/asphub.png","language":"CSS","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Ng5AppEx\n\nThis project was generated with [Angular CLI](https://github.com/angular/angular-cli) version 1.7.3.\n\n## Development server\n\nRun `ng serve` for a dev server. Navigate to `http://localhost:4200/`. The app will automatically reload if you change any of the source files.\n\n## Code scaffolding\n\nRun `ng generate component component-name` to generate a new component. You can also use `ng generate directive|pipe|service|class|guard|interface|enum|module`.\n\n## Build\n\nRun `ng build` to build the project. The build artifacts will be stored in the `dist/` directory. Use the `-prod` flag for a production build.\n\n## Running unit tests\n\nRun `ng test` to execute the unit tests via [Karma](https://karma-runner.github.io).\n\n## Running end-to-end tests\n\nRun `ng e2e` to execute the end-to-end tests via [Protractor](http://www.protractortest.org/).\n\n## Further help\n\nTo get more help on the Angular CLI use `ng help` or go check out the [Angular CLI README](https://github.com/angular/angular-cli/blob/master/README.md).\n\n## Tutorial - Steps\n\nAngular Sample Application made with Angular 5 and Angular Material\n\n\u003e This tutorial is made with inspired from AngularCRUD example with NG5 + Bootstrap found [here](https://appdividend.com/2018/01/21/angular-5-crud-tutorial-example-scratch/)\n\n### **Step 1**\n#### Install Angular via CLI.\n\n```bash\nnpm install -g @angular/cli\n```\n\n### **Step 2**\n#### Create a new project\n\u003e **Note:** Configuring default style extension to SCSS\n\u003e\n\u003e `ng set defaults.styleExt scss`\n```bash\nng new ng5AppEx\n```\n\n### **Step 3**\n#### Make three components of the application.\n\nCreate one directory inside `src/app` folder called components.\n```bash\nng g c index\nng g c create\nng g c edit\n```\nWe have created three components. Each component will do its job. Here we are establishing the single responsibility principle for every component.\n\nIt makes a separate folder inside `src/app` directory. We need to move all these three folders inside `components` folder.\n\nAlso, we need to change the app.module.ts file, to write the correct path of the imported components. By default, it’s an app directory.\n\n### **Step 4**\n#### Routing and Navigation\nThe Angular Router enables navigation from one view to the next as users perform application tasks.\nFirst, we need to import the routing modules inside our app.module.ts file.\n```typescript\n// app.module.ts\nimport { RouterModule } from '@angular/router';\n\nimports: [\n  BrowserModule, RouterModule\n]\n```\n\u003e Configuration\n\nWhen we have created the components, it’s by default path is different and now we have moved to the components, so now its path is different. So, first, we need to change that path in `app.module.ts` file.\n\nOkay, now we need to configure the routes. So make one file inside app directory called routerConfig.ts file.\n\nWrite the following code in it.\n\u003e `routerConfig.ts`\n```ts\nimport { Routes } from '@angular/router';\nimport { CreateComponent } from './components/create/create.component';\nimport { EditComponent } from './components/edit/edit.component';\nimport { IndexComponent } from './components/index/index.component';\n\nexport const appRoutes: Routes = [\n  {\n    path: '',\n    pathMatch: 'full',\n    redirectTo: 'index'\n  },\n  {\n    path: 'index',\n    component: IndexComponent\n  },\n  {\n    path: 'create',\n    component: CreateComponent\n  },\n  {\n    path: 'edit/:id',\n    component: EditComponent\n  }\n];\n```\nWe have defined one array, and inside that array, we have registered the different routes with their components. Finally, we have exported it.\n\nNow, import this object inside `app.module.ts` and register the module.\n\n```ts\n// app.module.ts\nimport { appRoutes } from './routerConfig';\n\nimports: [\n    BrowserModule,\n    RouterModule.forRoot(appRoutes)\n]\n```\n\n### **Step 5**\n#### Define the Router outlet\nIn the `app.component.html` file, make the following changes on code\n```html\n\u003cdiv class=\"t-c\"\u003e\n  \u003ch1\u003e\n    Welcome to {{title}}!!\n  \u003c/h1\u003e\n  \u003cnav\u003e\n    \u003ca routerLink=\"create\" routerLinkActive=\"active\"\u003eAdd coins\u003c/a\u003e\n  \u003c/nav\u003e\n  \u003crouter-outlet\u003e\u003c/router-outlet\u003e\n\u003c/div\u003e\n```\nAlso, we need to change the title attribute in `app.component.ts`\n\n```ts\n// app.component.ts\n\nimport { Component } from '@angular/core';\n\n@Component({\n  selector: 'app-root',\n  templateUrl: './app.component.html',\n  styleUrls: ['./app.component.scss']\n})\nexport class AppComponent {\n  title = 'the NG world';\n}\n```\n\nAdd some styles on `app.component.scss`\n\n```scss\n.t {\n  \u0026-l { text-align: left; }\n  \u0026-c { text-align: center; }\n  \u0026-r { text-align: right; }\n  \u0026-j { text-align: justify; }\n}\n```\n**_OR_**\n\ncan be write the global styles on `styles.scss`\n\n### **Step 6**\nStyles for layout with Angular Material\n\nMore Details: [https://material.angular.io/guide/getting-started](https://material.angular.io/guide/getting-started)\n\nInstall Angular Material and Angular CDK\n```bash\nnpm install --save @angular/material @angular/cdk\n```\nAnimations\n```bash\nnpm install --save angular/material2-builds angular/cdk-builds\n```\nGesture Support\n```bash\nnpm install --save hammerjs\n```\n\n#### Customising the Material theme\n\u003e `style.scss`\n```scss\n// @import \"~@angular/material/prebuilt-themes/indigo-pink.css\";\n\n@import '~@angular/material/theming';\n// Plus imports for other components in your app.\n\n// Include the common styles for Angular Material. We include this here so that you only\n// have to load a single css file for Angular Material in your app.\n// Be sure that you only ever include this mixin once!\n@include mat-core();\n\n// Define the palettes for your theme using the Material Design palettes available in palette.scss\n// (imported above). For each palette, you can optionally specify a default, lighter, and darker\n// hue. Available color palettes: https://www.google.com/design/spec/style/color.html\n$candy-app-primary: mat-palette($mat-indigo);\n$candy-app-accent:  mat-palette($mat-pink, A200, A100, A400);\n\n// The warn palette is optional (defaults to red).\n$candy-app-warn:    mat-palette($mat-red);\n\n// Create the theme object (a Sass map containing all of the palettes).\n$candy-app-theme: mat-light-theme($candy-app-primary, $candy-app-accent, $candy-app-warn);\n\n// Include theme styles for core and each component used in your app.\n// Alternatively, you can import and @include the theme mixins for each component\n// that you are using.\n@include angular-material-theme($candy-app-theme);\n\nhtml, body {\n  margin: 0;\n}\n\n...\n\n.mat-toolbar {\n  a {\n    color: currentColor;\n  }\n  .mat-button {\n    padding: 0 14px;\n  }\n}\n```\n\n#### Importing Modules for material Support\n\n\u003e `app.module.ts`\n\n```ts\n...\nimport { FormsModule } from '@angular/forms';\nimport {\n  MatIconModule,\n  MatButtonModule,\n  MatToolbarModule,\n  MatInputModule,\n  MatSidenavModule,\n  MatCardModule\n} from '@angular/material';\nimport { BrowserAnimationsModule } from '@angular/platform-browser/animations';\n\n...\n\n@NgModule({\n  declarations: [\n    AppComponent,\n    IndexComponent,\n    CreateComponent,\n    EditComponent\n  ],\n  imports: [\n    BrowserModule,\n    RouterModule.forRoot(appRoutes),\n    BrowserAnimationsModule,\n    MatIconModule,\n    MatButtonModule,\n    MatToolbarModule,\n    MatInputModule,\n    MatSidenavModule,\n    MatCardModule\n  ],\n  exports: [\n    MatIconModule,\n    MatButtonModule,\n    MatToolbarModule,\n    MatInputModule,\n    MatSidenavModule,\n    MatCardModule\n  ],\n  providers: [],\n  bootstrap: [AppComponent]\n})\nexport class AppModule { }\nexport class MaterialModule { }\n```\n\n#### Adding CSS For Material Icons\n\u003e `index.html`\n```html\n\u003clink href=\"https://fonts.googleapis.com/icon?family=Material+Icons\" rel=\"stylesheet\"\u003e\n```\n\n#### Import `hammerjs`\n\u003e `main.ts`\n```ts\nimport 'hammerjs';\n```\n\n#### Creating Layout with Material\n\u003e `app.component.html`\n\n```html\n\u003cmat-toolbar color=\"primary\"\u003e\n  \u003cmat-toolbar-row\u003e\n    \u003ca routerLink=\"index\" routerLinkActive=\"active\" mat-button\u003e\n      \u003cmat-icon class=\"icon\"\u003ehome\u003c/mat-icon\u003e\n    \u003c/a\u003e\n    \u003ch1\u003e\n      Welcome to {{title}}!!\n    \u003c/h1\u003e\n    \u003cspan class=\"spacer\"\u003e\u003c/span\u003e\n    \u003ca routerLink=\"create\" routerLinkActive=\"active\" mat-button\u003e\n      \u003cmat-icon class=\"icon\"\u003eadd\u003c/mat-icon\u003e\n      \u003cspan\u003eCoin\u003c/span\u003e\n    \u003c/a\u003e\n  \u003c/mat-toolbar-row\u003e\n\u003c/mat-toolbar\u003e\n\n\u003cmat-sidenav-container class=\"example-container\"\u003e\n  \u003cmat-sidenav mode=\"side\" opened\u003e\n    Sidenav content\n  \u003c/mat-sidenav\u003e\n  \u003cmat-sidenav-content\u003e\n    \u003crouter-outlet\u003e\u003c/router-outlet\u003e\n  \u003c/mat-sidenav-content\u003e\n\u003c/mat-sidenav-container\u003e\n```\n\n### **Step 7**\n#### Proper layouts for content area\n\u003e `index.component.html`\n```html\n\u003cmain class=\"main\"\u003e\n    index works!\n\u003c/main\u003e\n```\n\u003e `create.component.html`\n```html\n\u003cmain class=\"main\"\u003e\n    create works!\n\u003c/main\u003e\n```\n\u003e `edit.component.html`\n```html\n\u003cmain class=\"main\"\u003e\n    index works!\n\u003c/main\u003e\n```\n\n#### Adding some CSS\n\u003e `style.scss`\n```scss\n...\n\nmain {\n  padding: 15px;\n}\n```\n\n### **Step 8**\n#### Adding Responsive Grids\n\nYou can either to use Bootstrap / any other grids or can be write a new grid system\n\nI have a extracted a subset of Bootstrap-4 for Grid and basic functionalities. You can avail this copy on this [link](https://github.com/asphub/bootstrap-4-grid)\n\nAdd `scss` folder and `bootstrap.scss` directly on the `src` folder\n\nAdding Bootstrap CSS globally\n\u003e `.angular-cli.json`\n```JSON\n...\n\n\"styles\": [\n  \"bootstrap.scss\",\n  \"styles.scss\"\n],\n\n...\n```\n\n### **Step 9**\n#### Make a form in the create a component file.\nFirst, our `create.component.ts` file looks like this.\n```ts\nimport { Component, OnInit } from '@angular/core';\n\n@Component({\n  selector: 'app-create',\n  templateUrl: './create.component.html',\n  styleUrls: ['./create.component.scss']\n})\nexport class CreateComponent implements OnInit {\n\n  title = 'Add Coin';\n  constructor() { }\n\n  ngOnInit() {\n  }\n\n}\n```\nAnd then, we need to make the `create.component.html` form design.\n\n```html\n\u003cmain class=\"main\"\u003e\n  \u003cdiv class=\"row\"\u003e\n    \u003cdiv class=\"col-lg-4 col-md-6\"\u003e\n      \u003cmat-card class=\"form-card\"\u003e\n        \u003cmat-card-header\u003e\n          \u003cdiv mat-card-avatar\u003e\u003cmat-icon class=\"icon\"\u003emonetization_on\u003c/mat-icon\u003e\u003c/div\u003e\n          \u003cmat-card-title\u003eCoins\u003c/mat-card-title\u003e\n          \u003cmat-card-subtitle\u003eCreate\u003c/mat-card-subtitle\u003e\n        \u003c/mat-card-header\u003e\n        \u003cmat-card-content\u003e\n          \u003cdiv class=\"form-container\"\u003e\n            \u003cmat-form-field\u003e\n              \u003cinput matInput placeholder=\"Coin Name\"\u003e\n            \u003c/mat-form-field\u003e\n            \u003cmat-form-field\u003e\n              \u003cinput matInput placeholder=\"Coin Price\"\u003e\n            \u003c/mat-form-field\u003e\n          \u003c/div\u003e\n        \u003c/mat-card-content\u003e\n        \u003cmat-card-actions\u003e\n          \u003cdiv class=\"spacer\"\u003e\u003c/div\u003e\n          \u003cbutton mat-button color=\"accent\"\u003eAdd\u003c/button\u003e\n        \u003c/mat-card-actions\u003e\n      \u003c/mat-card\u003e\n    \u003c/div\u003e\n  \u003c/div\u003e\n\u003c/main\u003e\n```\n\nAdding some styles 😉\n\n```scss\n.mat-card {\n  \u0026 \u003e \u0026-actions {\n    display: flex;\n    flex-direction: row;\n    align-items: center;\n    white-space: nowrap;\n    box-sizing: border-box;\n  }\n}\n\n.form-container {\n  display: flex;\n  padding: 30px 0;\n  flex-direction: column;\n  \u0026 \u003e * {\n    width: 100%;\n  }\n}\n```\n\n### **Step 10**\n#### Configure HttpClientModule\n\n\u003e `HttpClientModule` is a new API that came with 4.3, it has updated API's with support for progress events, json deserialization by default, Interceptors and many other great features. See more [here](https://angular.io/guide/http), whereas `HttpModule` is the older API and will eventually be deprecated.\n\nGo to the `app.module.ts` file. Include the `HttpClientModule` in it.\n```ts\nimport {HttpClientModule} from '@angular/common/http';\n...\n\nimports: [\n  ...\n\n  HttpClientModule,\n\n  ...\n],\n```\n\n### **Step 11**\n#### Create services to send http requests\n\nType the following command in your terminal.\n```bash\nng g service coin\n```\n\nIt will create the following classes.\n\n1. `coin.service.ts`\n2. `coin.service.spec.ts`\n\nNow, import the service file into the `app.module.ts` file.\n```ts\nimport { CoinService } from './coin.service';\n\nproviders: [CoinService]\n```\n\n### **Step 12**\n#### Configure `node.js` MongoDB backend.\n\nNext step, would be to create `node.js` and Express backend to store the data. Create one file in the project root called `server.js`\n\nNow, we need to install the express framework and other dependencies via NPM, so let us do it first.\n```bash\nnpm install --save express body-parser cors mongoose nodemon\n```\nSwitch to newly created `server.js` file and enter the following code into it.\n\n\u003e `server.js`\n```js\nvar express = require('express'),\n  path = require('path'),\n  bodyParser = require('body-parser'),\n  cors = require('cors'),\n  mongoose = require('mongoose');\n\nconst app = express();\n\nvar port = process.env.PORT || 4000;\n\nvar server = app.listen(function(){\n  console.log('Listening on port ' + port);\n});\n```\nNext thing is we need to create the **MongoDB** database and connect it with our express application.\n\n\u003e Note: You need to have installed MongoDB database on your server or local otherwise first you need to download it and start the **MongoDB** server.\n\nCreate one config folder inside project root. In that create one file called `DB.js`.\n\n\u003e `DB.js`\n```js\nmodule.exports = {\n   DB: 'mongodb://localhost:27017/angularcrud'\n};\n```\nImport this file into our `server.js` file and use **mongoose** to set up a database connection with **MongoDB**. You need to copy the whole `server.js` file; I am about to show so that nothing will left and lead us to error.\n\n\u003e `server.js`\n```js\nconst express = require('express'),\n  path = require('path'),\n  bodyParser = require('body-parser'),\n  cors = require('cors'),\n  mongoose = require('mongoose'),\n  config = require('./config/DB');\n\nmongoose.Promise = global.Promise;\nmongoose.connect(config.DB).then(\n  () =\u003e { console.log('Database is connected') },\n  err =\u003e { console.log('Cannot connect to the database' + err) }\n);\n\nconst app = express();\napp.use(bodyParser.json());\napp.use(cors());\nconst port = process.env.PORT || 4000;\n\nconst server = app.listen(port, function () {\n  console.log('Listening on port ' + port);\n});\n```\n\n### **Step 13**\n#### Create Express routes for our application\nNow, we need to create two folders in root called `expressRoutes` and `models`.\n\nIn models folder, create one model called `Coin.js`.\n```js\nvar mongoose = require('mongoose');\nvar Schema = mongoose.Schema;\n\n// Define collection and schema for Items\nvar Coin = new Schema({\n  name: {\n    type: String\n  },\n  price: {\n    type: Number\n  }\n},{\n    collection: 'coins'\n});\n\nmodule.exports = mongoose.model('Coin', Coin);\n```\nIn the expressRoutes folder, create one file called `coinRoutes.js`.\n\n\u003e `coinRoutes.js`\n```js\nvar express = require('express');\nvar app = express();\nvar coinRoutes = express.Router();\n\n// Require Item model in our routes module\nvar Coin = require('../models/Coin');\n\n// Defined store route\ncoinRoutes.route('/add').post(function (req, res) {\n  var coin = new Coin(req.body);\n   coin.save()\n    .then(item =\u003e {\n    res.status(200).json({'coin': 'Coin added successfully'});\n    })\n    .catch(err =\u003e {\n    res.status(400).send(\"unable to save to database\");\n    });\n});\n\n// Defined get data(index or listing) route\ncoinRoutes.route('/').get(function (req, res) {\n   Coin.find(function (err, coins){\n    if(err){\n      console.log(err);\n    }\n    else {\n      res.json(coins);\n    }\n  });\n});\n\n// Defined edit route\ncoinRoutes.route('/edit/:id').get(function (req, res) {\n  var id = req.params.id;\n  Coin.findById(id, function (err, coin){\n      res.json(coin);\n  });\n});\n\n//  Defined update route\ncoinRoutes.route('/update/:id').post(function (req, res) {\n   Coin.findById(req.params.id, function(err, coin) {\n    if (!coin)\n      return next(new Error('Could not load Document'));\n    else {\n      coin.name = req.body.name;\n      coin.price = req.body.price;\n\n      coin.save().then(coin =\u003e {\n          res.json('Update complete');\n      })\n      .catch(err =\u003e {\n            res.status(400).send(\"unable to update the database\");\n      });\n    }\n  });\n});\n\n// Defined delete | remove | destroy route\ncoinRoutes.route('/delete/:id').get(function (req, res) {\n   Coin.findByIdAndRemove({_id: req.params.id}, function(err, coin){\n        if(err) res.json(err);\n        else res.json('Successfully removed');\n    });\n});\n\nmodule.exports = coinRoutes;\n```\nHere, I have defined all the routes related to CRUD application.\n\nThis file will be included in our `server.js` file.\n\n```js\ncoinRoutes = require('./expressRoutes/coinRoutes');\n\napp.use('/coins', coinRoutes);\n```\n\n### **Step 14**\n#### Insert the value in the MongoDB.\nFrom the front end side, we need to set up `HttpClientModule` and fire up the HTTP Post call to the NodeJS server.\n\n\u003e `server.js`\n```javascript\nconst express = require('express'),\n  path = require('path'),\n  bodyParser = require('body-parser'),\n  cors = require('cors'),\n  mongoose = require('mongoose'),\n  config = require('./config/DB'),\n  coinRoutes = require('./expressRoutes/coinRoutes');\n\nmongoose.Promise = global.Promise;\nmongoose.connect(config.DB).then(\n    () =\u003e {console.log('Database is connected') },\n    err =\u003e { console.log('Can not connect to the database'+ err)}\n  );\n\nconst app = express();\napp.use(bodyParser.json());\napp.use(cors());\nconst port = process.env.PORT || 4000;\n\napp.use('/coins', coinRoutes);\n\nconst server = app.listen(port, function(){\n  console.log('Listening on port ' + port);\n});\n```\n\nWe need to include the `ReactiveFormsModule` in the `app.module.ts` file.\n```ts\nimport { ReactiveFormsModule } from '@angular/forms';\n...\n@NgModule({\n  ...\n  imports:[\n    ...\n    ReactiveFormsModule,\n    ...\n  ],\n  ...\n});\n```\nThen, we are validating the forms. So first write the form HTML in the `create.component.html`.\n\u003e `create.component.html`\n```html\n\u003cform [formGroup]=\"coinForm\" novalidate\u003e\n  \u003cmat-card class=\"form-card\"\u003e\n    \u003cmat-card-header\u003e\n      \u003cdiv mat-card-avatar\u003e\n        \u003cmat-icon class=\"icon\"\u003emonetization_on\u003c/mat-icon\u003e\n      \u003c/div\u003e\n      \u003cmat-card-title\u003eCoins\u003c/mat-card-title\u003e\n      \u003cmat-card-subtitle\u003eCreate\u003c/mat-card-subtitle\u003e\n    \u003c/mat-card-header\u003e\n    \u003cmat-card-content\u003e\n      \u003cdiv class=\"form-container\"\u003e\n        \u003cmat-form-field\u003e\n          \u003cinput matInput placeholder=\"Coin Name\" formControlName=\"coinName\"\u003e\n          \u003cmat-error *ngIf=\"coinName.invalid\"\u003eCoin Name is required\u003c/mat-error\u003e\n        \u003c/mat-form-field\u003e\n        \u003cmat-form-field\u003e\n          \u003cinput type=\"number\" min=\"1\" matInput placeholder=\"Coin Price\" formControlName=\"coinVal\"\u003e\n          \u003cmat-error *ngIf=\"coinVal.invalid\"\u003eCoin value Must be a number and greater than 0\u003c/mat-error\u003e\n        \u003c/mat-form-field\u003e\n      \u003c/div\u003e\n    \u003c/mat-card-content\u003e\n    \u003cmat-card-actions\u003e\n      \u003cdiv class=\"spacer\"\u003e\u003c/div\u003e\n      \u003cbutton mat-button color=\"accent\" (click)=\"addCoin(coinForm.value.coinName, coinForm.value.coinVal)\" [disabled]=\"coinForm.pristine || coinForm.invalid\"\u003eAdd\u003c/button\u003e\n    \u003c/mat-card-actions\u003e\n  \u003c/mat-card\u003e\n\u003c/form\u003e\n```\n\nAlso, we need to write the logic of validation in the `create.component.ts` file.\n\u003e `create.component.ts`\n```ts\nimport { Component, OnInit } from '@angular/core';\nimport {\n  NgForm,\n  FormGroup,\n  Validators,\n  FormControl,\n  FormBuilder,\n  FormGroupDirective,\n  AbstractControl\n} from '@angular/forms';\nimport { ErrorStateMatcher } from '@angular/material/core';\n\nimport { CoinService } from '../../coin.service';\n\n/** Error when invalid control is dirty, touched, or submitted. */\nexport class FormControlValidation implements ErrorStateMatcher {\n  isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {\n    const isSubmitted = form \u0026\u0026 form.submitted;\n    return !!(control \u0026\u0026 control.invalid \u0026\u0026 (control.dirty || control.touched || isSubmitted));\n  }\n}\n\n@Component({\n  selector: 'app-create',\n  templateUrl: './create.component.html',\n  styleUrls: ['./create.component.scss']\n})\nexport class CreateComponent implements OnInit {\n\n  coinForm: FormGroup;\n  constructor(private coinservice: CoinService, private fb: FormBuilder) {\n    this.createForm();\n  }\n\n  coinName = new FormControl('', [\n    Validators.required\n  ]);\n  coinVal = new FormControl('', [\n    Validators.required,\n    Validators.min(1)\n  ]);\n\n  resetForm(formGroup: FormGroup) {\n    let control: AbstractControl = null;\n    formGroup.reset();\n    formGroup.markAsUntouched();\n    Object.keys(formGroup.controls).forEach((name) =\u003e {\n      control = formGroup.controls[name];\n      control.setErrors(null);\n    });\n  }\n\n  createForm() {\n    this.coinForm = this.fb.group({\n      coinName: new FormControl('', [\n        Validators.required\n      ]),\n      coinVal: new FormControl('', [\n        Validators.required,\n        Validators.min(1)\n      ])\n    });\n  }\n  addCoin(name, price) {\n    this.coinservice.addCoin(name, price);\n    this.coinForm.reset();\n    this.resetForm(this.coinForm);\n  }\n\n  ngOnInit() {\n  }\n}\n```\n\nWrite the `coin.service.ts` file to insert the data into the database.\n\u003e `coin.service.ts`\n```ts\nimport { Injectable } from '@angular/core';\nimport { HttpClient } from '@angular/common/http';\n\n@Injectable()\nexport class CoinService {\n\n  constructor(private http: HttpClient) { }\n\n  addCoin(name, price) {\n    const uri = 'http://localhost:4000/coins/add';\n    const obj = {\n      name: name,\n      price: price\n    };\n    this.http.post(uri, obj)\n      .subscribe(res =\u003e console.log('Done'));\n  }\n}\n```\nStart the `node.js` server by typing: `node server`. If all the database configuration is right then, you can see the data is inserting into the database.\n\n### **Step 15**\n#### Display the data to the frontend\nImport Material DataTable for displaying the data\n\u003e `app.module.ts`\n```ts\n  import {\n    ...\n    MatTableModule,\n    ...\n  } from '@angular/material';\n\n  ...\n\n  @NgModule({\n    ...\n    imports: [\n      ...\n      MatTableModule,\n      ...\n    ],\n    exports: [\n      ...\n      MatTableModule,\n      ...\n    ],\n    ...\n  })\n```\n\nIn the `index.component.ts` file, write the following code.\n```ts\n  import { Component, OnInit } from '@angular/core';\n  import { HttpClient } from '@angular/common/http';\n  import { Observable } from 'rxjs/Observable';\n  import { MatTableDataSource } from '@angular/material';\n\n  import { CoinService } from './../../coin.service';\n\n  @Component({\n    selector: 'app-index',\n    templateUrl: './index.component.html',\n    styleUrls: ['./index.component.scss']\n  })\n  export class IndexComponent implements OnInit {\n    coins: any;\n    displayedColumns = ['name', 'price', 'action'];\n    dataSource = this.coins;\n\n    constructor(private http: HttpClient, private service: CoinService) { }\n\n    getCoins() {\n      this.service.getCoins().subscribe(res =\u003e {\n        this.coins = res;\n        this.dataSource = new MatTableDataSource(this.coins);\n      });\n    }\n\n    ngOnInit() {\n      this.getCoins();\n    }\n  }\n```\nIn the `index.component.html` file, write the following code for Material Data Table.\n```html\n  \u003cmain class=\"main\"\u003e\n    \u003cdiv class=\"col-md-6\"\u003e\n      \u003cmat-table #table [dataSource]=\"dataSource\"\u003e\n        \u003c!-- Name Column --\u003e\n        \u003cng-container matColumnDef=\"name\"\u003e\n          \u003cmat-header-cell *matHeaderCellDef\u003e Name \u003c/mat-header-cell\u003e\n          \u003cmat-cell *matCellDef=\"let element\"\u003e {{element.name}} \u003c/mat-cell\u003e\n        \u003c/ng-container\u003e\n\n        \u003c!-- Price Column --\u003e\n        \u003cng-container matColumnDef=\"price\"\u003e\n          \u003cmat-header-cell *matHeaderCellDef\u003e Price \u003c/mat-header-cell\u003e\n          \u003cmat-cell *matCellDef=\"let element\"\u003e {{element.price}} \u003c/mat-cell\u003e\n        \u003c/ng-container\u003e\n\n        \u003c!-- Action Column --\u003e\n        \u003cng-container matColumnDef=\"action\"\u003e\n          \u003cmat-header-cell *matHeaderCellDef class=\"w-120\"\u003e Action \u003c/mat-header-cell\u003e\n          \u003cmat-cell *matCellDef=\"let element\" class=\"w-120 t-r\"\u003e\n              \u003ca [routerLink]=\"['/edit', element._id]\" mat-icon-button color=\"primary\"\u003e\n                \u003cmat-icon aria-label=\"Edit Coin\"\u003eedit\u003c/mat-icon\u003e\n              \u003c/a\u003e\n              \u003ca [routerLink]=\"\" mat-icon-button color=\"warn\"\u003e\n                \u003cmat-icon aria-label=\"Delete Coin\"\u003edelete\u003c/mat-icon\u003e\n              \u003c/a\u003e\n          \u003c/mat-cell\u003e\n        \u003c/ng-container\u003e\n\n        \u003cmat-header-row *matHeaderRowDef=\"displayedColumns\"\u003e\u003c/mat-header-row\u003e\n        \u003cmat-row *matRowDef=\"let row; columns: displayedColumns;\"\u003e\u003c/mat-row\u003e\n      \u003c/mat-table\u003e\n    \u003c/div\u003e\n  \u003c/main\u003e\n```\n\nAdd some style for column width\n\u003e `index.component.scss`\n```scss\n  .w-120 {\n    max-width: 120px;\n  }\n```\nService get and edit coins\n\u003e `coin.service.ts`\n```ts\n  import { Injectable } from '@angular/core';\n  import { HttpClient } from '@angular/common/http';\n  import {\n    FormGroup,\n    FormBuilder,\n    Validators\n  } from '@angular/forms';\n  import { Observable } from 'rxjs/Observable';\n  import 'rxjs/add/operator/map';\n\n  @Injectable()\n  export class CoinService {\n\n    result: any;\n    constructor(private http: HttpClient) { }\n\n    addCoin(name, price) {\n      const uri = 'http://localhost:4000/coins/add';\n      const obj = {\n        name: name,\n        price: price\n      };\n      this.http.post(uri, obj)\n        .subscribe(res =\u003e console.log('Done'));\n    }\n\n    getCoins() {\n      const uri = 'http://localhost:4000/coins';\n      return this.http.get(uri).map(res =\u003e {\n        return res;\n      });\n    }\n\n    editCoin(id) {\n      const uri = 'http://localhost:4000/coins/edit/' + id;\n      return this.http.get(uri).map(res =\u003e {\n        return res;\n      });\n    }\n  }\n```\n\n### **Step 16**\n#### Edit and Delete the Coins\nNow, first, we need to fetch the data from the database and display in the edit form. So first, write the code for the Imports and methods in `edit.component.ts`\n```ts\n  import { Component, OnInit } from '@angular/core';\n  import {\n    NgForm,\n    FormGroup,\n    Validators,\n    FormControl,\n    FormBuilder,\n    FormGroupDirective,\n    AbstractControl\n  } from '@angular/forms';\n  import { ErrorStateMatcher } from '@angular/material/core';\n\n  import { CoinService } from '../../coin.service';\n  import { ActivatedRoute, Router } from '@angular/router';\n\n  /** Error when invalid control is dirty, touched, or submitted. */\n  export class FormControlValidation implements ErrorStateMatcher {\n    isErrorState(control: FormControl | null, form: FormGroupDirective | NgForm | null): boolean {\n      const isSubmitted = form \u0026\u0026 form.submitted;\n      return !!(control \u0026\u0026 control.invalid \u0026\u0026 (control.dirty || control.touched || isSubmitted));\n    }\n  }\n\n  @Component({\n    selector: 'app-edit',\n    templateUrl: './edit.component.html',\n    styleUrls: ['./edit.component.scss']\n  })\n  export class EditComponent implements OnInit {\n\n    coin: any;\n    coinForm: FormGroup;\n    title = 'Edit Coin';\n    constructor(private route: ActivatedRoute, private router: Router, private service: CoinService, private fb: FormBuilder) {\n      this.createForm();\n    }\n    coinName = new FormControl('', [\n      Validators.required\n    ]);\n    coinVal = new FormControl('', [\n      Validators.required,\n      Validators.min(1)\n    ]);\n\n    resetForm(formGroup: FormGroup) {\n      let control: AbstractControl = null;\n      formGroup.reset();\n      formGroup.markAsUntouched();\n      Object.keys(formGroup.controls).forEach((name) =\u003e {\n        control = formGroup.controls[name];\n        control.setErrors(null);\n      });\n    }\n\n    createForm() {\n      this.coinForm = this.fb.group({\n        coinName: new FormControl('', [\n          Validators.required\n        ]),\n        coinVal: new FormControl('', [\n          Validators.required,\n          Validators.min(1)\n        ])\n      });\n    }\n\n    updateCoin(name, price) {\n      this.route.params.subscribe(params =\u003e {\n        this.service.updateCoin(name, price, params['id']);\n        this.router.navigate(['index']);\n      });\n    }\n\n    ngOnInit() {\n      this.route.params.subscribe(params =\u003e {\n        this.coin = this.service.editCoin(params['id']).subscribe(res =\u003e {\n          this.coin = res;\n        });\n      });\n    }\n  }\n```\nNow, also write the code into the `coin.service.ts` file.\n```ts\n  import { Injectable } from '@angular/core';\n  import { HttpClient } from '@angular/common/http';\n  import { Observable } from 'rxjs/Observable';\n  import 'rxjs/add/operator/map';\n\n  @Injectable()\n  export class CoinService {\n\n    result: any;\n    constructor(private http: HttpClient) { }\n\n    addCoin(name, price) {\n      const uri = 'http://localhost:4000/coins/add';\n      const obj = {\n        name: name,\n        price: price\n      };\n      this\n        .http\n        .post(uri, obj)\n        .subscribe(res =\u003e\n          console.log('Done'));\n    }\n\n    getCoins() {\n      const uri = 'http://localhost:4000/coins';\n      return this\n        .http\n        .get(uri)\n        .map(res =\u003e {\n          return res;\n        });\n    }\n\n    editCoin(id) {\n      const uri = 'http://localhost:4000/coins/edit/' + id;\n      return this\n        .http\n        .get(uri)\n        .map(res =\u003e {\n          return res;\n        });\n    }\n\n    updateCoin(name, price, id) {\n      const uri = 'http://localhost:4000/coins/update/' + id;\n\n      const obj = {\n        name: name,\n        price: price\n      };\n      this\n        .http\n        .post(uri, obj)\n        .subscribe(res =\u003e console.log('Done'));\n    }\n\n    deleteCoin(id) {\n      const uri = 'http://localhost:4000/coins/delete/' + id;\n\n      return this\n        .http\n        .get(uri)\n        .map(res =\u003e {\n          return res;\n        });\n    }\n  }\n```\nWrite the following code in the `edit.component.html` file for the edit Form.\n```html\n  \u003cmain class=\"main\"\u003e\n    \u003cdiv class=\"row\"\u003e\n      \u003cdiv class=\"col-lg-4 col-md-6\"\u003e\n        \u003cform [formGroup]=\"coinForm\" novalidate\u003e\n          \u003cmat-card class=\"form-card\"\u003e\n            \u003cmat-card-header\u003e\n              \u003cdiv mat-card-avatar\u003e\n                \u003cmat-icon class=\"icon\"\u003emonetization_on\u003c/mat-icon\u003e\n              \u003c/div\u003e\n              \u003cmat-card-title\u003eCoins\u003c/mat-card-title\u003e\n              \u003cmat-card-subtitle\u003eCreate\u003c/mat-card-subtitle\u003e\n            \u003c/mat-card-header\u003e\n            \u003cmat-card-content\u003e\n              \u003cdiv class=\"form-container\"\u003e\n                \u003cmat-form-field\u003e\n                  \u003cinput matInput placeholder=\"Coin Name\" formControlName=\"coinName\" [(ngModel)] = \"coin.name\"\u003e\n                  \u003cmat-error *ngIf=\"coinName.invalid\"\u003eCoin Name is required\u003c/mat-error\u003e\n                \u003c/mat-form-field\u003e\n                \u003cmat-form-field\u003e\n                  \u003cinput type=\"number\" min=\"1\" matInput placeholder=\"Coin Price\" formControlName=\"coinVal\" [(ngModel)] = \"coin.price\"\u003e\n                  \u003cmat-error *ngIf=\"coinVal.invalid\"\u003eCoin value Must be a number and greater than 0\u003c/mat-error\u003e\n                \u003c/mat-form-field\u003e\n              \u003c/div\u003e\n            \u003c/mat-card-content\u003e\n            \u003cmat-card-actions\u003e\n              \u003cdiv class=\"spacer\"\u003e\u003c/div\u003e\n              \u003cbutton mat-button color=\"accent\" (click)=\"updateCoin(coinForm.value.coinName, coinForm.value.coinVal)\" [disabled]=\"coinForm.pristine || coinForm.invalid\"\u003eAdd\u003c/button\u003e\n            \u003c/mat-card-actions\u003e\n          \u003c/mat-card\u003e\n        \u003c/form\u003e\n      \u003c/div\u003e\n    \u003c/div\u003e\n  \u003c/main\u003e\n```\nAdding some styles\n\u003e `edit.component.scss`\n```scss\n  .mat-card {\n    \u0026 \u003e \u0026-actions {\n      display: flex;\n      flex-direction: row;\n      align-items: center;\n      white-space: nowrap;\n      box-sizing: border-box;\n    }\n  }\n\n  .form-container {\n    display: flex;\n    padding: 30px 0;\n    flex-direction: column;\n    \u0026 \u003e * {\n      width: 100%;\n    }\n  }\n```\n\nAdding Delete Functionality on list page\n```html\n  \u003ca [routerLink]=\"\" (click)=\"deleteCoin(element._id)\" mat-icon-button color=\"warn\"\u003e\n    \u003cmat-icon aria-label=\"Delete Coin\"\u003edelete\u003c/mat-icon\u003e\n  \u003c/a\u003e\n```\nMethod for delete in `index.component.ts`\n```ts\n  ...\n\n  deleteCoin(id) {\n    this.service.deleteCoin(id).subscribe(res =\u003e {\n      this.getCoins();\n    });\n  }\n\n  ...\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasphub%2Fng5appex","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fasphub%2Fng5appex","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fasphub%2Fng5appex/lists"}