1.0.0 • Published 7 months ago

inovabiz-template-frontend v1.0.0

Weekly downloads
-
License
-
Repository
-
Last release
7 months ago

Fury - Angular 11+ Material Design Admin Template

Introduction

Fury is a creative material design admin template built with Angular 8+ and the Angular-CLI. It extends the Material Design components built by the Angular 8+ team and it offers you everything you need to get started with your next CRM, CMS or dashboard based project.

Support is available through email, ThemeForest comments or chat. If you purchased the theme and love it, consider giving it a 5-star rating here on ThemeForest. It really helps pushing out more updates and adding more great features.

Table of Contents

Getting Started

In this section you will find the basic folder structure and everything you need to get the theme up and running the first time to start developing.

Folder Structure

NameDescription
angular-cli.jsonUsed for configuration of project specific settings. You can add external styles and scripts, change the output folder, add assets, add environment files and more.
e2eWill be used for end-to-end tests to ensure functionality for users before deploying.
node_modulesAll external modules used are here. Do not mess with this folder, as it is auto-generated by using npm install.
package.jsonContains all dependencies used for production and development.
srcContains all Angular 11+ Typescript code, assets and basically everything the end user will have access to.
tslint.jsonAngular-CLI includes an automatic Typescript-Linter, which can be configured with this file.

npm.io


Using Angular-CLI

Angular-CLI allows you to create a new App in a matter of seconds and provides an awesome way to generate scaffolds for basically all Angular-Components. You can take a look at what commands are available here.

In this article, we are going to install Angular-CLI and it's prerequisites and then generate our first project with a few various components.


###Prerequisites Before we can install Angular-CLI we will have to get a few thing set up first. To run Angular-CLI we will need to install these 2 prerequisites first.

  • NodeJS v4 or newer
    and
  • Typings v1 or newer

A detailed instruction on how to install NodeJS is available here.

After installing NodeJS there is just one thing left to do: Simply install Typings globally by running the command npm install -g typings and wait for npm to do the dirty work.

If you are on a *UNIX environment, you might have to run the command as administrator. This is done by simply prepending sudo: sudo npm install -g typings


###Installing Angular-CLI Installing Angular-CLI is as simple as running this simple command:

npm install -g @angular/cli@latest
or sudo npm install -g @angular/cli@latest

and the package manager npm will do the rest.


###Generating the first Component Now that we have installed all prerequisites it's time to start developing our app. Angular-CLI offers a lot of assistance and allows you to generate basically all Angular 11+-Components there are. (In a smart way!)

To generate our first component we simply open up a terminal and navigate in our Angular 11+-App. Now we simply run ng g component client and we get a new component in /src/app/client with the following files:

  • client.component.ts
  • client.component.html
  • client.component.css
  • client.component.spec.ts

The files client.component.ts and client.component.spec.ts contain the most code, the other files only contain placeholders.

client.component.ts

import { Component, OnInit } from '@angular/core';

@Component({
  moduleId: module.id,
  selector: 'app-client',
  templateUrl: 'client.component.html',
  styleUrls: ['client.component.css']
})
export class ClientComponent implements OnInit {

  constructor() { }

  ngOnInit() {
  }

}

By executing this short command, we just saved ourselves a lot of time creating all these Component files and boilerplate code.

Syntax for all commands are available here.


###Generating a Service in a specific folder Now we have our component, but what if we want to share some data between components and need to create a service to manage this all. Well, we probably would want the service to be in the correct folder, either right in the components folder or in the shared folder in /src/app/.

Either way, with Angular-CLI we can generate in any folder, wherever we want. Simply use the path (relative to /src/app/) and use it as the name of the generated component.

ng g service shared/client
or ng g service client/shared/client

Or anything you need. Afterward we will find two generated files in our specified folder: client.service.ts and client.service.spec.ts.

client.service.ts

import { Injectable } from '@angular/core';

@Injectable()
export class ClientService {

  constructor() { }

}

###Live-Preview and App-Start

Now that we have generated our components, we sure want to see how the result will look like. Luckily Angular-CLI comes pre-configured with a Live Compile and Reload Server for which you simply have to run ng serve and after a few seconds your site will be live at http://localhost:4200.

demo image

All changes you now make to your app will automatically be compiled and your open browser window will be reloaded.

These were the first steps with the awesome Angular-CLI and Angular 11+. Following we are going to get more in detail about developing with Angular-CLI and using the power of Angular 8+ right.

Customizing

Everything shown in the demo can also be customized and most things are generated dynamically, for example the navigation menu.

Add a Menu Item

Menu Items can be added in runtime by importing the SidenavService and adding menu items there. Here's an example:

export class TestComponent {
  constructor(
    private sidenavService: SidenavService
  ) {
    let components = sidenavService.addItem('Components', 'layers', '/components', 2);
                     sidenavService.addSubItem(components, 'Buttons', '/components/buttons', 1);
   }
}

The function addItem accepts 4 parameters:

sidenavService.addItem('The name shown in the navigation menu',
                       'the material icon to be used', 
                       'the route to put in [routerLink]',
                       'position in menu as number');

To create a dropdown menu with sub-items you can use the addSubItem function. The parameters are similar:

sidenavService.addSubItem(referenceToParentItem (as shown in the example above),
                       'The name shown in the navigation menu',
                       'the material icon to be used', 
                       'the route to put in [routerLink]',
                       'position in sub-menu as number');

Breadcrumbs

Breadcrumbs are generated automatically from the current route, but you can also add custom user-friendly names. Adding "friendly names" for routes is done like this:

export class TestComponent {
  constructor(
    private breadcrumbService: BreadcrumbService
  ) {
    breadcrumbService.addFriendlyNameForRoute('/components', "Components");
    breadcrumbService.addFriendlyNameForRoute('/components/buttons', "Buttons");
   }
}

The first parameter is the route to name, the second is the new breadcrumb name for this route.

Receive, send and map data to a server with GET and POST requests

Receiving data from a server to process or display it in Angular 11+ can be quite tricky with the new observables and syntax. Here you'll find an example how you can do this.

First of all create an abstract BaseService where you configure your Backend-URL and the correct paths for your backend.

base.service.ts

import { Http, Headers } from '@angular/http';
import { Inject, Injectable } from '@angular/core';
import 'rxjs/add/operator/map';

@Injectable()
export abstract class BaseService {
  config: String;
  http:   Http;
  modelName: string;
  model: any;

  constructor(@Inject(Http) http: Http) {
    this.http   = http;
    this.config = 'http://yourBackend.url'
  }

  mapListToModelList (list: Array<Object>) {
    list.forEach((item, index) => {
      list[index] = this.mapModel(item);
    });

    return list;
  }

  mapModel(model: any) {
    return this.model(model);
  }

  findById(id: number, populate: Array<string> = null) {
    return new Promise((resolve, reject) => {
      let url = this.config + '/' + this.modelName + '/' + id;

      if (populate) {
        url = url + '?populate=' + populate.join(', ');
      }

      console.log('URL', url);

      this.http.get(url)
        .map(res => res.json())
        .subscribe(res => {
          if (res.error) {
            reject(res.error);
          } else {
            resolve(this.mapModel(res));
          }
        });
    });
  }

  find(populate: Array<string> = null) {
    return new Promise((resolve, reject) => {
      let url = this.config + '/' + this.modelName;

      if (populate) {
        url = url + '?populate=' + populate.join(', ');
      }

      this.http.get(url)
        .map(res => res.json())
        .subscribe(res => {
          if (res.error) {
            reject(res.error);
          } else {
            resolve(this.mapListToModelList(res));
          }
        });
    });
  }

  upsert(model: any) {
    return new Promise((resolve, reject) => {
      let url = this.config + '/api/' + this.modelName;

      var headers = new Headers();
      headers.append('Content-Type', 'application/json');
      headers.append('Accept', 'application/json');

      this.http.put(url, JSON.stringify(model), {headers : headers})
        .map(res => res.json())
        .subscribe(res => {
          console.log(res);
          if (res.error) {
            reject(res.error);
          } else {
            resolve(this.mapModel(res));
          }
        });
    });
  }

  create(model: any) {
    return new Promise((resolve, reject) => {
      let url = this.config + '/' + this.modelName;

      var headers = new Headers();
      headers.append('Content-Type', 'application/json');
      headers.append('Accept', 'application/json');

      this.http.post(url, JSON.stringify(model), {headers : headers})
        .map(res => res.json())
        .subscribe(res => {
          console.log(res);
          if (res.error) {
            reject(res.error);
          } else {
            resolve(this.mapModel(res));
          }
        });
    });
  }
}

Then you'll need a more specific service, in this example it's called CustomerService. This Service extends the BaseService inheriting all it's functions.

You will need to define a variable modelName which will appear in the called GET path in BaseService.

customer.service.ts

import { Injectable, Inject } from '@angular/core';
import { Http } from "@angular/http";
import { BaseService } from "../../shared/base.service";
import { Customer } from "./customer.model";

@Injectable()
export class CustomerService extends BaseService {
  model: any;
  modelName = 'customer';

  constructor(@Inject(Http) http:Http) {
    super(http);

    this.model = (construct: any) => {
      return new Customer(construct);
    };
  }
}

Before using the data, you should map it as a class, so Typescript knows what it is and you know later on too. This is a sample Customer class.

customer.model.ts

export class Customer {
  firstName: string;
  lastName: string;

  constructor(model: any = null) {
    if (model) {
      this.firstName = model.firstName;
      this.lastName = model.lastName;
    }
  }
}

Last but not least you can finally inject the CustomerService and call one of these functions:

customer.component.ts

import { Component, OnInit } from '@angular/core';
import { CustomerService } from "../shared/customer.service";
import { Customer } from "../shared/customer.model";

@Component({
  selector: 'app-customer',
  templateUrl: './customer.component.html',
  styleUrls: ['./customer.component.css']
})
export class CustomerComponent implements OnInit {
  customers: Customer[] = [ ];

  constructor(private customerService: CustomerService) { }

  ngOnInit() {
    this.customerService.find().then((customers) => {
      this.customers = customers;
    });
  }
}

Note: You may need to adjust the import paths according to your directory structure.

URL mapping on an Apache Server

To allow for the URL to automatically route to the appropriate component on an Apache server like the internal ng serve server, you need to create a .htaccess file that routes all requests to the index.html file.

Here is an example how we did it on our demo-page:

<IfModule mod_rewrite.c>
  RewriteEngine On
  RewriteBase /
  RewriteEngine On
  RewriteCond %{HTTPS} off
  RewriteRule ^(.*)$ https://%{HTTP_HOST}%{REQUEST_URI} [L,R=301]
  RewriteRule ^index\.html$ - [L]
  RewriteCond %{REQUEST_FILENAME} !-f
  RewriteCond %{REQUEST_FILENAME} !-d
  RewriteRule . /index.html [L]
</IfModule>

Note: We're using https, if you don't have or need https, remove the s from https:// and the RewriteCond with %{HTTPS} off.

Credits

In our theme we use various different external libraries. All of these libraries have their own complete documentation which can help you develop. In this section we list links to those libraries.

  • Angular Material - Awesome library for Material Components and core component in our theme.
  • Google Material Icons - Simply the best Material Icons out there.
  • RxJS - Angular 11+ Dependency - A new approach to how data can be handled in Observables.
  • HighlightJS - Simple Syntax highlighting. Our theme includes a directive to apply the highlighting quickly to <code> blocks.
  • Normalize.css - Convenient reset of browser-specific styles to industry-standard styling.
  • Lodash - "A modern JavaScript utility library delivering modularity, performance & extras."
  • Roboto Font - Google's official Material Design Typography font.
  • Google Maps for Angular - Google's official Material Design Typography font.

Assets

  • All Avatars used are from Adorable Avatars licensed MIT and can therefore be also used in your application and are included in the download.
  • Backgrounds used are from Oxygenna. Marked as "Free to use in commercial projects" and can therefore not be bundled in the download, but can easily be added afterwards.

All other assets shown in the demo are included in the download. All external libraries are usually loaded with npm install, except "HighlightJS", which is bundled.