آموزش توسعه یک بلاگ با Blazor Server
Build a Complete Blog App with Blazor Server - Step-by-Step Tutorial from Scratch by Abhay Prince
You will learn about fundamentals of Blazor Server, Routing, Shared Reusable Components, Custom Authentication, EF Core Code First, Passing data from parent to child components and vice versa, Passing events from child to parent components, Forms validations and submissions, styling components, using javascript with blazor. third party components integration with blazor, blazor lifecycle events, authentication and authorization in blazor server, programtically navigating between component pages, multiple routes paths for single component page, dynamic routes and getting data from routes, authorized view and much more...
Build Real App in Angular 10 and ASP.Net Web API
These are 2 of the hottest frameworks right now for the ‘back-end’ (Microsoft’s ASP.NET Core) and the ‘front-end’ (Google’s Angular) and are well worth spending the time to learn.
This course starts from scratch, you neither need to know Angular 1 nor Angular 2
We will start from nothing and incrementally build this property dealing application front-end using Angular 10.
And then we will connect our front-end with the Web-API until we have a fully functional Web Application that we will publish to Firebase and then on IIS.
We are proud to present the first beta release of Kendo UI for Angular 2. It’s been designed specifically for Angular 2. Written in Typescript, built as native Query-free components and distributed as NPM packages, Kendo UI for Angular 2 makes integrating UI components into ng2 a piece of cake for developers. In this beta release, you’ll find the business application essential building blocks — form elements, grid and data visualization components.
AngularJs و i18n
The new i18n story in Angular
Internationalization support in Angular has been very poor so far. You might know that there’s anngLocale
module you need to include, which is used by a couple components, likengPluralize
,date
andcurrency
filter to name a few, and that’s pretty much it. As we’ve already discussed, there’s so much more that comes into play when internationalizing an application, which is why there’s finally a new solution evolving that will bring first-class i18n support to the Angular framework.
سری کار با Web API
My road for the series is as follows,
RESTful Day #1: Enterprise level application architecture with Web APIs using Entity Framework, Generic Repository pattern and Unit of Work.
RESTful Day #2: Inversion of control using dependency injection in Web APIs using Unity Container and Bootstrapper.
RESTful Day #3: Resolve dependency of dependencies using Inversion of Control and dependency injection in Asp.net Web APIs with Unity Container and Managed Extensibility Framework (MEF).
RESTful Day #4: Custom URL Re-Writing/Routing using Attribute Routes in MVC 4 Web APIs.
RESTful Day #5: Basic Authentication and Token based custom Authorization in Web APIs using Action Filters.
RESTful Day #6: Request logging and Exception handing/logging in Web APIs using Action Filters, Exception Filters and nLog.
RESTful Day #7: Unit testing ASP.NET Web APIs controllers using nUnit.
RESTful Day #8: Extending OData support in ASP.NET Web APIs.
- بهبود کپسوله سازی قسمتهای مختلف برنامه با بسته بندی آنها در ماژولهای متفاوت
- فراهم آوردن امکان lazy loading و بهبود کارآیی برنامه
انواع ماژولهای توصیه شدهی در برنامههای Angular
منهای App Module پیشفرض یک برنامههای Angular، ایجاد سه نوع ماژول دیگر نیز در جهت سازماندهی اینگونه برنامهها توصیه میشوند:
- Core Module
هدف از آن فراهم آوردن سرویسهای Singleton اشتراکی بین کامپوننتها و ماژولهای مختلف برنامه است. علت اینجا است که سیستم تزریق وابستگیهای Angular، به ازای هر ماژولی که Lazy loaded باشد، سرویس تزریقی در آنها را مجددا وهله سازی میکند. به همین جهت نیاز است تک ماژول اختصاصی را برای مدیریت سرویسهایی که نیازی است تنها یکبار در طول عمر برنامه وهله سازی شوند، تدارک ببینیم و Core Module مکان مناسبی برای اینکار است.
همچنین Code Module باید شامل کامپوننتهایی در سطح برنامه باشد. دراینجا منظور از «در سطح برنامه»، کامپوننتهایی که قرار است در بین تمام ماژولها به اشتراک گذاشته شوند، نیست. منظور تنها کامپوننتهایی هستند که در App Component اصلی برنامه قرار است استفاده شوند؛ مانند منوی راهبری بالای سایت.
- Shared Module
هدف از آن مدیریت و بسته بندی کامپوننتها، دایرکتیوها و Pipes اشتراکی بین تمام اجزای برنامه است. برای مثال کامپوننت «لطفا منتظر بمانید ...» اگر قرار است در تمام قسمتهای برنامه استفاده شود، نیاز است در Shared Module تعریف شود. از این جهت که در یک برنامهی Angular نمیتوان یک کامپوننت را بین دو ماژول مختلف به اشتراک گذاشت. به همین جهت نیاز است یک مکان مرکزی برای تعریف این کامپوننتهای اشتراکی ایجاد شود و سپس این تک ماژول را در قسمتهای مختلف برنامه، بدون مشکل مورد استفاده قرار داد.
- Feature Module
این ماژولها به ازای هر ویژگی برنامه ایجاد شده و کامپوننتها، سرویسها، دایرکتیوها و Pipes اختصاصی آن ویژگی را بسته بندی میکنند.
ایجاد Core Module
فرض کنید میخواهید اطلاعات کاربر جاری لاگین شده را در طول عمر برنامه نگهداری کنید و از آن در تمام قسمتهای برنامه استفاده نمائید. یک چنین سرویسی نیاز است دارای طول عمر Singleton باشد و تنها یکبار وهله سازی شود تا اطلاعات کاربر جاری از دست نرود. به همین جهت بهترین مکان تعریف این سرویس، در Core Module است.
برای این منظور در ساختار برنامهی خود، پوشهی جدید src\app\core را ایجاد میکنیم. سپس فایل core.module.ts را به صورت ذیل در آن تعریف خواهیم کرد:
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { RouterModule } from '@angular/router'; import { UserRepositoryService } from './user-repository.service'; import { NavBarComponent } from './nav-bar.component'; import { AccountMenuComponent } from './account-menu.component'; @NgModule({ imports: [ CommonModule, RouterModule ], exports: [ NavBarComponent, AccountMenuComponent ], declarations: [ NavBarComponent, AccountMenuComponent ], providers: [ UserRepositoryService ] }) export class CoreModule { };
- سپس سرویسهای اشتراکی و Singleton برنامه در قسمت providers آن قرار میگیرند.
- در اینجا همچنین دو کامپوننت منو که توسط app.component.ts مورد استفاده قرار میگیرند نیز import شدهاند.
- فایلهای account-menu.component.ts، nav-bar.component.ts و user-repository.service.ts نیز به درون پوشهی src\app\core منتقل خواهند شد (به همراه تمام فایلهای html و css متناظر با آنها).
- اگر دقت کنید، قسمت exports این ماژول نیز مقدار دهی شدهاست. چون این کامپوننتها قرار است خارج از این ماژول و در AppModule استفاده شوند، نیاز است آنها را به صورت خروجی نیز معرفی کنیم.
اکنون جهت استفادهی از این قابلیتها، تنها کافی است تعریف CoreModule را به AppModule در فایل app.module.ts اضافه کنیم:
import { CoreModule } from "./core/core.module"; @NgModule({ imports: [ //... CoreModule, //... RouterModule.forRoot(appRoutes) ], //... }) export class AppModule { }
ایجاد Shared Modules
در Shared Module اجزایی را قرار خواهیم داد که قرار است در بیش از یک ماژول مورد استفاده قرار گیرند. به همین جهت در ساختار برنامهی خود، پوشهی جدید src\app\shared را ایجاد میکنیم. سپس در آن، ماژول جدید shared.module.ts را ایجاد خواهیم کرد:
import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import { LoadingSpinnerComponent } from './loading-spinner.component'; @NgModule({ imports: [ CommonModule ], declarations: [ LoadingSpinnerComponent ], exports: [ LoadingSpinnerComponent, CommonModule ], providers: [ ] }) export class SharedModule { };
از این جهت که اجزای خروجی این ماژول قرار است در Feature Moduleها استفاده شوند، CommonModule مورد استفادهی در آنها نیز در قسمت exports ذکر شدهاست.
اکنون جهت استفادهی از این قابلیتها، تنها کافی است تعریف SharedModule را به AppModule در فایل app.module.ts اضافه کنیم:
import { CoreModule } from "./core/core.module"; import { SharedModule } from "./shared/shared.module"; @NgModule({ imports: [ //... CoreModule, SharedModule, //... RouterModule.forRoot(appRoutes) ], //... }) export class AppModule { }
ایجاد Feature Modules
این مورد نکتهی ویژهای را به همراه ندارد و همانند ایجاد سایر ماژولهای برنامهاست. برای مثال ویژگی مدیریت کاربران، به همراه تمام اجزای آن درون ماژول کاربران قرار میگیرد و به همین ترتیب برای سایر ویژگیهای دیگر برنامه. ایجاد و مدیریت اینگونه ماژولها توسط Angular CLI بسیار سادهاست:
> ng g m users -m app.module --routing > ng g c users/users-list
دستور دوم نیز کامپوننتی را به این ماژول اضافه میکند؛ به همراه به روز رسانی تعاریف این ماژول.
فقط در اینجا SharedModule ایی را که پیشتر اضافه کردیم، به قسمت imports آن اضافه میکنیم:
import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { SharedModule } from '../shared/shared.module'; import { UsersListComponent } from './users-list.component'; @NgModule({ imports: [ RouterModule, SharedModule ], declarations: [ UsersListComponent ], exports: [ ], providers: [ ] }) export class UsersModule { };
Web API Development in .NET 8 in 2 Hours | ASP.NET CORE | RESTFUL API
00:00:00 Introduction
00:03:06 What is Web API & Why create Web API
00:10:21 How Web API Works in Theory
00:14:49 How Web API Works (Demo with Minimal APIs)
00:27:32 What is a Web API Framework
00:33:27 ASP.NET Core Middleware Pipeline
00:37:34 Web API Controller
00:42:25 Routing in Web API
00:51:17 Model Binding
01:01:06 Model Validation with DataAnnatation
01:08:07 Model Validation with ValidationAttribute
01:15:10 Web API Return Types
01:21:30 In Mememory Repository
01:25:01 Model Validation with Action Filter
01:35:30 Read Endpoint
01:36:55 Create Endpoint
01:46:45 Validating Create Endpoint with ActionFilter
01:51:23 Update Endpoint
01:59:48 Exception Hanlding with Exception Filter
02:05:48 Delete Endpoint
UI-Router ابزاری برای مسیریابی در AngularJS است که این امکان را برایتان فراهم میکند تا بخشهای برنامه رابط کاربریتان را به شکل یک ماشین حالت ساماندهی کنید. برخلاف سرویس route$ که بر اساس مسیریابی URLها ساماندهی شده و کار میکند، UI-Router بر اساس حالتها کار میکند، که این حالتها میتوانند در صورت لزوم مسیریابی هم داشته باشند.
UI-Router یکی از افزونههای مجموعه Angular-ui، و پاراگراف بالا معرفی آن در صفحه خانگیش است (تقریبا!). این افزونه جزئیات مفصلی دارد و در این مطلب تنها به معرفی آن خواهم پرداخت (بر اساس مطالب صفحه خانگیش). پیش از ادامه پیشنهاد میکنم اگر مطالب زیر را نخواندهاید ابتدا آنها را مرور کنید:
برای استفاده از UI-Router باید:
- فایل جاوا اسکریپت آن را دانلود کنید (released یا minified).
- در صفحه اصلی برنامهتان پس از include کردن فایل اصلی AngularJS فایل angular-ui-router.js (یا angular-ui-router.min.js) را include کنید.
- 'ui.router' را به لیست وابستگیهای ماژول اصلی اضافه کنید.
<!doctype html> <html ng-app="myApp"> <head> <script src="//ajax.googleapis.com/ajax/libs/angularjs/1.1.5/angular.min.js"></script> <script src="js/angular-ui-router.min.js"></script> <script> var myApp = angular.module('myApp', ['ui.router']); // For Component users, it should look like this: // var myApp = angular.module('myApp', [require('angular-ui-router')]); </script> ... </head> <body> ... </body> </html>
حالتها و viewهای تو در تو
قابلیت اصلی UI-Router امکان تعریف حالتها و vieweهای تو در تو است. در مطلب مسیریابی در AngularJs #بخش اول دایرکتیو ng-view معرفی شده است. هنگام استفاده از سرویس route$ با این دایرکتیو میتوان محل مورد نظر برای بارگذاری محتویات مربوط به مسیرها را مشخص کرد. دایرکتیو ui-view در UI-Router همین نقش را دارد. فرض کنید این کد فایل index.html باشد:<!-- index.html --> <body> <div ui-view></div> <!-- We'll also add some navigation: --> <a ui-sref="state1">State 1</a> <a ui-sref="state2">State 2</a> </body>
در ادامه برای هر کدام از حالتها یک template اضافه میکنیم:
فایل state1.html:
<!-- partials/state1.html --> <h1>State 1</h1> <hr/> <a ui-sref="state1.list">Show List</a> <div ui-view></div>
<!-- partials/state2.html --> <h1>State 2</h1> <hr /> <a ui-sref="state2.list">Show List</a> <div ui-view></div>
دو نکته قابل توجه در این templateها وجود دارد. اول اینکه همانطور که میبینید templateها خود شامل تگی با دایرکتیو ui-view هستند. و دوم مقدار دایرکتیو ui-sref است که به صورت state1.list و state2.list آمده است. این جدا سازی با نقطه نشان دهنده سلسله مراتب حالتهاست. یعنی حالتهای state1 و state2 هرکدام حالت فرزندی به نام list دارند. در ادامه وقتی حالتها و مسیریابی را در ()app.config تعریف کنیم این مسائل از هالهای از ابهام که در آن هستند خارج میشوند! فعلا بیاید با راهنمای UI-Router پیش برویم و فایلهای template حالتهای فرزند را تعریف کنیم. templateهایی که قرار است در ui-view پدرانشان بارگذاری شوند:
<!-- partials/state1.list.html --> <h3>List of State 1 Items</h3> <ul> <li ng-repeat="item in items">{{ item }}</li> </ul>
<!-- partials/state2.list.html --> <h3>List of State 2 Things</h3> <ul> <li ng-repeat="thing in things">{{ thing }}</li> </ul>
myApp.config(['$stateProvider', '$urlRouterProvider', function($stateProvider, $urlRouterProvider) { // // For any unmatched url, redirect to /state1 $urlRouterProvider.otherwise("/state1"); // // Now set up the states $stateProvider .state('state1', { url: "/state1", templateUrl: "partials/state1.html" }) .state('state1.list', { url: "/list", templateUrl: "partials/state1.list.html", controller: function($scope) { $scope.items = ["A", "List", "Of", "Items"]; } }) .state('state2', { url: "/state2", templateUrl: "partials/state2.html" }) .state('state2.list', { url: "/list", templateUrl: "partials/state2.list.html", controller: function($scope) { $scope.things = ["A", "Set", "Of", "Things"]; } }) }]);
خصوصیت url مشخص کننده مسیر حالت است. این خصوصیت همان مقداریست که به عنوان پارامتر اول به ()routeProvider.when$ پاس میشد. در این پارامتر میشود متغیرهای url را هم به همان ترتیب تعریف کرد. مثلا اگر حالت state1 در آدرسش یک پارامتر id داشته باشد میشود آن را به این ترتیب تعریف کرد:
.state('state1', { url: "/state1/:id", templateUrl: "partials/state1.html" })
$stateParams.id
.state('list', { parent: "state1", url: "/list", templateUrl: "partials/state1.list.html", controller: function($scope) { $scope.items = ["A", "List", "Of", "Items"]; } }) .state('list', { parent: "state2", url: "/list", templateUrl: "partials/state2.list.html", controller: function($scope) { $scope.items = ["A", "List", "Of", "Items"]; } })
- وابستگیهای فراهم شده در حالت پدر به وسیله "resolve"
- دادههای سفارشی مشخص شده در خصوصیت data حالت پدر
.state('state1', { url: "/state1", templateUrl: "partials/state1.html", data:{ foodata: 'addorder' } })
$state.current.data.foodata
Viewهای نامگذاری شده و چندگانه
<!-- index.html --> <body> <div ui-view="viewA"></div> <div ui-view="viewB"></div> <!-- Also a way to navigate --> <a ui-sref="route1">Route 1</a> <a ui-sref="route2">Route 2</a> </body>
myApp.config(function ($stateProvider) { $stateProvider .state('index', { url: "", views: { "viewA": { template: "index.viewA" }, "viewB": { template: "index.viewB" } } }) .state('route1', { url: "/route1", views: { "viewA": { template: "route1.viewA" }, "viewB": { template: "route1.viewB" } } }) .state('route2', { url: "/route2", views: { "viewA": { template: "route2.viewA" }, "viewB": { template: "route2.viewB" } } }) });
چند نکته
.state('list', { parent: "state1", url: "/list", templateUrl: "partials/state1.list.html", controller: "state1ListController as listCtrl1" } }) .state('list', { parent: "state2", url: "/list", templateUrl: "partials/state2.list.html", controller: "state2ListController as listCtrl2" } })
حالتهای انتزاعی
حساسیت به حروف بزرگ و کوچک
- در فایل "angular-ui-router.js" عبارت "new RegExp(compiled)" را پیدا کرده و آن را به "RegExp(compiled, 'i')" تبدیل کنید. و یا در "angular-ui-router.min.js" (هرکدام از فایلها که استفاده میکنید) عبارت new RegExp(o) را پیدا کرده و آن را به new RegExp(o, "i") تبدیل کنید. همین؛ صدایش را هم در نیاورید!
// angular-material-feature.module.ts import { NgModule } from '@angular/core'; // Import angular kendo angular import { MatFormFieldModule, MatInputModule, MatButtonModule, MatButtonToggleModule, MatDialogModule, MatIconModule, MatSelectModule, MatToolbarModule, MatDatepickerModule, DateAdapter, MAT_DATE_FORMATS, MAT_DATE_LOCALE, MatTableModule, MatCheckboxModule, MatRadioModule, MatCardModule, fadeInContent, MatListModule, MatProgressBarModule, MatTabsModule } from '@angular/material'; import { MatSidenavModule, MatSlideToggleModule, } from '@angular/material'; import { MatMenuModule } from '@angular/material/menu'; @NgModule({ declarations: [ // KendoGridPaginationComponent ], imports: [ MatSidenavModule, MatSlideToggleModule, MatInputModule, MatFormFieldModule, MatButtonModule, MatButtonToggleModule, MatDialogModule, MatIconModule, MatSelectModule, MatToolbarModule, MatDatepickerModule, MatCheckboxModule, MatRadioModule, MatCardModule, MatMenuModule, MatListModule, MatProgressBarModule, MatTabsModule ], exports: [ MatSidenavModule, MatSlideToggleModule, MatInputModule, MatFormFieldModule, MatButtonModule, MatButtonToggleModule, MatDialogModule, MatIconModule, MatSelectModule, MatToolbarModule, MatDatepickerModule, MatCheckboxModule, MatRadioModule, MatCardModule, MatMenuModule, MatListModule, MatProgressBarModule, MatTabsModule ], providers: [ ] }) export class AngularMaterialFeatureModule { }
// kendo-feature.module.ts import { NgModule } from '@angular/core'; // Import kendo angular ui import { ButtonsModule } from '@progress/kendo-angular-buttons'; import { GridModule, ExcelModule } from '@progress/kendo-angular-grid'; import { DropDownsModule } from '@progress/kendo-angular-dropdowns'; import { InputsModule } from '@progress/kendo-angular-inputs'; import { DateInputsModule } from '@progress/kendo-angular-dateinputs'; import { DialogsModule } from '@progress/kendo-angular-dialog'; import { RTL } from '@progress/kendo-angular-l10n'; import { LayoutModule } from '@progress/kendo-angular-layout'; import { WindowService, WindowRef, WindowCloseResult, DialogService, DialogRef, DialogCloseResult } from '@progress/kendo-angular-dialog'; import { SnotifyModule, SnotifyService, SnotifyPosition, SnotifyToastConfig, ToastDefaults } from 'ng-snotify'; @NgModule({ declarations: [ ], imports: [ ButtonsModule, GridModule, ExcelModule, DropDownsModule, InputsModule, DateInputsModule, DialogsModule, LayoutModule, SnotifyModule, ], exports: [ ButtonsModule, GridModule, ExcelModule, DropDownsModule, InputsModule, DateInputsModule, DialogsModule, LayoutModule, ], providers: [ { provide: 'SnotifyToastConfig', useValue: ToastDefaults }, SnotifyService, // Enable Right-to-Left mode for Kendo UI components { provide: RTL, useValue: true }, ] }) export class KendoFeatureModule { }
// app.module.ts import { BrowserModule } from '@angular/platform-browser'; import { BrowserAnimationsModule } from '@angular/platform-browser/animations'; import { NgModule } from '@angular/core'; import { RouterModule } from '@angular/router'; import { AppRoutingModule } from './app-routing.module'; import { AppComponent } from './app.component'; @NgModule({ declarations: [ AppComponent ], imports: [ BrowserAnimationsModule, RouterModule, AppRoutingModule, ], providers: [], bootstrap: [AppComponent] }) export class AppModule { }
// app.component.ts import { Component, ViewEncapsulation } from '@angular/core'; @Component({ selector: 'app-root', templateUrl: './app.component.html', styleUrls: ['./app.component.scss'], encapsulation: ViewEncapsulation.None, }) export class AppComponent { title = 'HowToKeepAngularDeploymentSizeSmall'; constructor() { } }
// app.component.html <router-outlet></router-outlet>
// app-routing.module.ts import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; const routes: Routes = [ { path: '', loadChildren: './projects/home/home.module#HomeModule' } ]; @NgModule({ imports: [RouterModule.forRoot(routes)], exports: [RouterModule] }) export class AppRoutingModule { }
// home.module.ts import { NgModule } from '@angular/core'; import { CommonModule } from '@angular/common'; import {AngularMaterialFeatureModule , KendoFeatureModule} from '../../modules/index'; import {HomeRoutingModule } from './home.routing'; import { HomeComponent } from './home.component'; import { IndexComponent } from './pages/index/index.component'; import {LoginComponent } from './pages/login/login.component'; @NgModule({ declarations: [ HomeComponent, IndexComponent, LoginComponent ], imports: [ CommonModule, HomeRoutingModule, AngularMaterialFeatureModule ], providers:[ ], entryComponents:[ LoginComponent ] }) export class HomeModule { }
// home.routing.ts import { NgModule } from '@angular/core'; import { Routes, RouterModule } from '@angular/router'; import { HomeComponent } from './home.component'; import { IndexComponent } from './pages/index/index.component'; const routes: Routes = [ { path: "", component: HomeComponent, children: [ { path: "", component: IndexComponent, data: { breadcrumb: " Index " } }, { path: "about", loadChildren: "./pages/aboutus/aboutus.module#AboutusModule" }, { path: "blog", loadChildren: "./pages/blog/blog.module#BlogModule" }, { path: "blog-detail", loadChildren: "./pages/blogdetail/blogdetail.module#BlogdetailModule" }, { path: "pricing", loadChildren: "./pages/pricing/pricing.module#PricingModule" }, { path: "contact", loadChildren: "./pages/contact/contact.module#ContactModule" } ] } ]; @NgModule({ imports: [RouterModule.forChild(routes)], exports: [RouterModule], }) export class HomeRoutingModule { }
// home.component.ts import { Component, OnInit, ViewEncapsulation } from '@angular/core'; import { MatDialog, MatDialogRef, MAT_DIALOG_DATA } from '@angular/material'; import { LoginComponent } from './pages/login/login.component'; @Component({ selector: 'app-home', templateUrl: './home.component.html', styleUrls: ['./home.component.scss'], encapsulation: ViewEncapsulation.None }) export class HomeComponent implements OnInit { constructor( private dialog: MatDialog) { } ngOnInit() { } public toggleModal(){ let dialogRef = this.dialog.open(LoginComponent, { }); } }
// home.component.scss @import '../../../assets/home/css/themify-icons.css'; @import '../../../assets/home/css/font-awesome.min.css'; @import '../../../assets/home/css/set1.css'; @import '../../../assets/home/css/bootstrap.min.css'; @import '../../../assets/home/css/style.css'; @import "~@angular/material/prebuilt-themes/indigo-pink.css";
// home.component.html <!--============================= HEADER =============================--> <div> <div> <div> <div> <div> <nav> <a href="index.html"><img src="../../../assets/home/images/logo.png" alt="logo"></a> <button type="button" data-toggle="collapse" data-target="#navbarNavDropdown" aria-controls="navbarNavDropdown" aria-expanded="false" aria-label="Toggle navigation"> <span></span> </button> <div id="navbarNavDropdown"> <ul> <li> <a target="_blank" [routerLink]="['/dashboard']">Dashboard</a> </li> <li> <a [routerLink]="['/about']">About</a> </li> <li> <a [routerLink]="['/contact']">Contact</a> </li> <li> <a [routerLink]="['/pricing']">Pricing</a> </li> <li> <a href="#" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false"> Blog <span></span> </a> <div> <a [routerLink]="['/blog']">Blog Listing</a> <a [routerLink]="['/blog-detail']">Blog Detail</a> </div> </li> <li> <a (click)='toggleModal()' style="cursor: pointer;">Login</a> </li> <li><a href="add-listing.html"><span></span> Add Listing</a></li> </ul> </div> </nav> </div> </div> </div> </div> </div> <!--//END HEADER --> <router-outlet></router-outlet> <!--============================= FOOTER =============================--> <footer> <div> <div> <div> <div> <i aria-hidden="true"></i> <p>503 Sylvan Ave, Mountain View<br> CA 94041, United States</p> </div> </div> <div> <div> <img src="../../../assets/home/images/footer-logo.png" alt="#"> </div> </div> <div> <ul> <li><a href="#"><i aria-hidden="true"></i></a></li> <li><a href="#"><i aria-hidden="true"></i></a></li> <li><a href="#"><i aria-hidden="true"></i></a></li> <li><a href="#"><i aria-hidden="true"></i></a></li> <li><a href="#"><i aria-hidden="true"></i></a></li> </ul> </div> </div> <div> <div> <div> <p>Copyright © 2017 Listed Inc. All rights reserved</p> <a href="#">Privacy</a> <a href="#">Terms</a> </div> </div> </div> </div> </footer> <!--//END FOOTER -->