Creating custom AngularJS directives for beginners

Creating custom AngularJS directives for beginners

<strong>Originally published </strong><em>at&nbsp;</em><a href="https://adrianmejia.com/blog/2016/04/08/creating-custom-angularjs-directives-for-beginners/" target="_blank">adrianmejia.com</a>

Directives are one of the most important concepts to understand Angular. This tutorial takes through the basics and beyond. We will cover how to build your own HTML extensions through directives.

Angular framework relies heavily on them to teach the browser new HTML tags. Directives are a powerful tool to create reusable web components. Directives not only could be defined as new HTML tags but also as attributes, CSS classes or even HTML comments. Angular comes with many built-in (core) directives that offer numerous functionalities to your web applications right away. Furthermore, it also allows us to define our own through custom directives. We are going to focus on the later.

Let’s say we want to create a new HTML component that the browsers doesn’t support yet, like a To-do list:

<my-todo list="todo" title="Angular Todo"></my-todo>

If you paste that code in any browser, it will not do much. We need to use Angular to teach the browser how to interpret this new HTML element called “my-todo”. We do this by defining a new directive with its attributes.

Let’s initialize our app and define our new directive:

Create a new file called “script.js”

var app = angular.module('myApp', []);

app.directive('myTodo', function(){
    return {
      restrict: 'EA',
      templateUrl: 'todo.tpl.html',
      scope: {
        list: '=',
        title: '@'
      }
    };
  });

Don’t get scared if you don’t understand what’s going on right now. By the end of this tutorial, you will be able to know what each line is doing.

In the first line, we initialize an angular module called “myApp”. That will return an “app” instance where we can start defining our Angular app.

We start by adding a directive called “myTodo”, notice that is different from “my-todo” that we used in the HTML code above. That’s because, by convention in HTML, tags names words are separated by a hyphen like “my-todo”. On the other hand, in Angular they match the same element with words joint together and capitalizing the beginning of each word, except the first one “myTodo”. This style of joining words is known as “camelCase”.

You will notice that a directive, takes a name “myTodo” and function. The later returns an object with a number of attributes depending on what we would like to accomplish. In our case, we have three attributes: restrict, templateUrl, and scope. Let’s explain each one in that exact order.

1. Restrict

The “restrict” attribute tells Angular, with one letter, how are we going to create our new directive. It can take four different values ‘E’, ‘A’, ‘C’, ‘M’ or combination of them like ‘EA’. Each one has it’s own meaning:

Taking our To-do example, with the combined value ‘EA’, means that will match any element with our directive as an attribute, and also, it will match any element defined as “”

It is a good practice only to use restrict to either ‘E’ or ‘A’ or both. Classes ‘C’ and comments ‘M’ could be easily misinterpreted. That’s why we are using just EA.

2.Template

Templates are just HTML code that could be reuse multiple times with different values or text. In order to be generic enough, they use placeholders tied to variables that could be easily replaced. Let’s create the “todo.tpl.html” with the following content:

todo.tpl.html
<h1>{{title}}</h1>
<div ng-repeat="todo in list">
  <input type="checkbox" ng-model="todo.completed"> {{todo.name}}
</div>


Notice that our template contains placeholders with a variable such as Creating custom AngularJS directives for beginners, which is going, to be replaced by real title text. Similarly, is going to be replaced with a task name.

We just used our first built-in Angular directive, in this tutorial, “ng-repeat”. This directive is going to take an array of elements, like our list and repeat itself for each one of elements and refer to them as “todo”. In other words, if the list contains 4 tasks, we are going to see 4 checkboxes each one with the name of the individual tasks. We are going to explain where “title” and “list” comes in the next section.

Going back to our directive definition, we could have used “template” attribute instead of “templateUrl” and take inline html code directly, but often is hard to read and we would prefer to use “templateUrl” and defined as a separated file.

As you might figure it out, “templateUrl” takes the name of the file containing the template. If all templates and code are in the same directory just the name of the file will do. If they are in a different folder you will need to specify the full path to reach it. To keep it simple, we are going to have all files in a single directory.

3. Scope

Scopes are key concept to understand Angular. Scope is what glues JavaScript code with HTML and allow us to replace placeholders from templates with real values.

In our directive definition, we are creating a new “isolated scope” with two elements:

Isolated scope
scope: {
  list: '=',
  title: '@'
}

If you remember from our template, these are exactly the two placeholders that we had “title” and “list”. The symbols = and @ looks a little mysterious but they are not too cryptic once we know what they mean.

  • @ Implies that the value of the attribute with the same name in the HTML element will be passed as a string. For instance, , will replace Creating custom AngularJS directives for beginners in our template for “The Directive”.
  • = Binds to the value of the expression and to the literal value. This means that if we have an attribute list=“todo” and “todo” is equal to 5, then it will be replaced to 5 and not to the literal text “todo”. In our case, “todo” is going to be an array of tasks.

Bear in mind, that in Angular we can have multiple scopes. So, our directives could be influenced by outer scopes. For instance, another scope could define “todo” as an array of elements. Here is where we introduce another important concept: controllers.

4. Controllers

The main purpose of controllers is to set initial values the scope and also add behavior through functions. We are going to use a controller to define the “todo” list that we want to render with our newly created directive.

The way we create controllers is by attaching the controller to our Angular app instance. Let’s go back to script.js and append the following:

script.js
app.controller('main', function($scope){
  $scope.todo = [
    {name: 'Create a custom directive', completed: true},
    {name: 'Learn about restrict', completed: true},
    {name: 'Master scopes', completed: false}
  ];
});

Noticed that we defined our controller with the name “main” and pass along a function with the “$scope” parameter. This is important since, whatever we attach to the “$scope” variable it will become available in templates and other directives. We just defined our todo list as an array of objects with two properties name and completed.

5.To-do directive

So far, we have been preparing the grounds for our directive. We have created:

  • “myApp” module
  • “myTodo” directive
  • “todo.tpl.html” template
  • “main” controller

Now, is the time to put everything together and make it work!

Let’s create an index.html page with the following:

<!DOCTYPE html>
<html>

  <head>
    <script data-require="[email protected]" data-semver="1.5.0" src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.0/angular.js"></script>
   <script src="script.js"></script>
  </head>

  <body ng-app="myApp">

    <div ng-controller="main">
  <my-todo list="todo" title="Angular To-do"></my-todo>
    </div>

  </body>
</html>

We add the AngularJS library first and then initialize the app using the built-in directive “ng-app”. Notice that this must match to module that we created “myApp” or it won’t work.

Later, we reference our controller using another core directive called “ng-controller”. Similarly to ng-app, it also takes a value that should match the one we defined, in this case “main” controller. This main controller defines our “todo” as an array of tasks with names and whether they have been completed or not.

Finally, we start using our new directive! It takes two attributes the title and a list. If you remember, we defined a template inside the directive definition, so it knows how to render the content.

That’s all you need to make it work. Now try it!

6.Next steps

By now you should be looking at our new To-do list. We can reuse this new directive with new to-do lists as many times as we want. Just passing different values to “list” in our “my-todo” the browser will be able to render it for us. We can also define another controller with a different $scope.todo and our directive will respond accordantly.

We just walked through the main attributes to create directives and discuss how to use them. We learnt how to isolate the scope of our directive and just allow certain parameters into our templates such as “list” and “title”. Also, used the “restrict” attribute to allow our directive be created either as a new HTML element or as an attribute. Finally, we explore how to use templates and bind it with our scope variables.

What are the best alternatives for angular js?

<img src="https://moriohcdn.b-cdn.net/193902114c.png">There are numerous frameworks and libraries used across the globe. If not angular, there are platforms like React, Vue, Aurelia and so on for app development.

There are numerous frameworks and libraries used across the globe. If not angular, there are platforms like React, Vue, Aurelia and so on for app development.

Angular 8 Node & Express JS File Upload

Angular 8 Node & Express JS File Upload

In this Angular 8 and Node.js tutorial, we are going to look at how to upload files on the Node server. To create Angular image upload component, we will be using Angular 8 front-end framework along with ng2-file-upload NPM package; It’s an easy to use Angular directives for uploading the files.

In this Angular 8 and Node.js tutorial, we are going to look at how to upload files on the Node server. To create Angular image upload component, we will be using Angular 8 front-end framework along with ng2-file-upload NPM package; It’s an easy to use Angular directives for uploading the files.

We are also going to take the help of Node.js to create the backend server for Image or File uploading demo. Initially, we’ll set up an Angular 8 web app from scratch using Angular CLI. You must have Node.js and Angular CLI installed in your system.

We’ll create the local server using Node.js and multer middleware. Multer is a node.js middleware for handling multipart/form-data, which is primarily used for uploading files. Once we are done setting up front-end and backend for our File uploading demo then, we’ll understand step by step how to configure file uploading in Angular 8 app using Node server.

Prerequisite

In order to show you Angular 8 File upload demo, you must have Node.js and Angular CLI installed in your system. If not then check out this tutorial: Set up Node JS

Run following command to install Angular CLI:

npm install @angular/cli -g

Install Angular 8 App

Run command to install Angular 8 project:

ng new angular-node-file-upload

# ? Would you like to add Angular routing? No
# ? Which stylesheet format would you like to use? CSS
cd angular-node-file-upload

Show Alert Messages When File Uploaded

We are going to install and configure ngx-toastr an NPM package which helps in showing the alert message when the file is uploaded on the node server.

npm install ngx-toastr --save

The ngx-toastr NPM module requires @angular/animations dependency:

npm install @angular/animations --save

Then, add the ngx-toastr CSS in angular.json file:

"styles": [
    "src/styles.css",
    "node_modules/ngx-toastr/toastr.css"
]

Import BrowserAnimationsModule and ToastrModule in app.module.ts file:

import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { ToastrModule } from 'ngx-toastr';
 
@NgModule({
  imports: [
    CommonModule,
    BrowserAnimationsModule, // required animations module
    ToastrModule.forRoot() // ToastrModule added
  ]
})

export class AppModule { }

Install & Configure ng-file-upload Directive

In this step, we’ll Install and configure ng-file-upload library in Angular 8 app. Run command to install ng-file-upload library.

npm install ng2-file-upload

Once the ng2-file-upload directive is installed, then import the FileSelectDirective and FormsModule in app.module.ts. We need FormsModule service so that we can create the file uploading component in Angular.

import { FileSelectDirective } from 'ng2-file-upload';
import { FormsModule } from '@angular/forms';

@NgModule({
  declarations: [
    FileSelectDirective
  ],
  imports: [
    FormsModule
  ]
})

export class AppModule { }

Setting Up Node Backend for File Upload Demo

To upload the file on the server, we need to set up a separate backend. In this tutorial, we will be using Node & Express js to create server locally along with multer, express js, body-parser, and dotenv libraries.

Run command to create backend folder in Angular app’s root directory:

mkdir backend && cd backend

In the next step, create a specific package.json file.

npm init

Run command to install required dependencies:

npm install express cors body-parser multer dotenv --save

In order to get rid from starting the server again and again, install nodemon NPM package. Use –-save-dev along with the npm command to register in the devDependencies array. It will make it available for development purpose only.

npm install nodemon --save-dev

Have a look at final pacakge.json file for file upload demo backend:

{
  "name": "angular-node-file-upload",
  "version": "1.0.0",
  "description": "Angualr 8 file upload demo app",
  "main": "server.js",
  "scripts": {
    "test": "echo \"Error: no test specified\" && exit 1",
    "start": "node server.js"
  },
  "author": "Digamber Rawat",
  "license": "ISC",
  "dependencies": {
    "body-parser": "^1.19.0",
    "cors": "^2.8.5",
    "dotenv": "^8.0.0",
    "express": "^4.17.1",
    "multer": "^1.4.1"
  },
  "devDependencies": {
    "nodemon": "^1.19.1"
  }
}

Create a file by the name of server.js inside backend folder:

Configure Server.js

To configure our backend we need to create a server.js file. In this file we’ll keep our backend server’s settings.

touch server.js

Now, paste the following code in backend > server.js file:

const express = require('express'),
  path = require('path'),
  cors = require('cors'),
  multer = require('multer'),
  bodyParser = require('body-parser');

// File upload settings  
const PATH = './uploads';

let storage = multer.diskStorage({
  destination: (req, file, cb) => {
    cb(null, PATH);
  },
  filename: (req, file, cb) => {
    cb(null, file.fieldname + '-' + Date.now())
  }
});

let upload = multer({
  storage: storage
});

// Express settings
const app = express();
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({
  extended: false
}));

app.get('/api', function (req, res) {
  res.end('File catcher');
});

// POST File
app.post('/api/upload', upload.single('image'), function (req, res) {
  if (!req.file) {
    console.log("No file is available!");
    return res.send({
      success: false
    });

  } else {
    console.log('File is available!');
    return res.send({
      success: true
    })
  }
});

// Create PORT
const PORT = process.env.PORT || 8080;
const server = app.listen(PORT, () => {
  console.log('Connected to port ' + PORT)
})

// Find 404 and hand over to error handler
app.use((req, res, next) => {
  next(createError(404));
});

// error handler
app.use(function (err, req, res, next) {
  console.error(err.message);
  if (!err.statusCode) err.statusCode = 500;
  res.status(err.statusCode).send(err.message);
});

Now, while staying in the backend folder run the below command to start the backend server:

nodemon server.js

If everything goes fine then you’ll get the following output:

[nodemon] 1.19.1
[nodemon] to restart at any time, enter `rs`
[nodemon] watching: *.*
[nodemon] starting `node server.js`
Connected to port 8080

Create Angular 8 File Upload Component

In this last step, we are going to create a file upload component in Angular 8 app using Express js API.

Get into the app.component.ts file and include the following code:

import { Component, OnInit } from '@angular/core';
import { FileUploader } from 'ng2-file-upload/ng2-file-upload';
import { ToastrService } from 'ngx-toastr';

const URL = 'http://localhost:8080/api/upload';

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

export class AppComponent implements OnInit {
  public uploader: FileUploader = new FileUploader({
    url: URL,
    itemAlias: 'image'
  });

  constructor(private toastr: ToastrService) { }

  ngOnInit() {
    this.uploader.onAfterAddingFile = (file) => {
      file.withCredentials = false;
    };
    this.uploader.onCompleteItem = (item: any, status: any) => {
      console.log('Uploaded File Details:', item);
      this.toastr.success('File successfully uploaded!');
    };
  }

}

Go to app.component.html file and add the given below code:

<div class="wrapper">
  <h2>Angular Image Upload Demo</h2>

  <div class="file-upload">
    <input type="file" name="image" ng2FileSelect [uploader]="uploader" accept="image/x-png,image/gif,image/jpeg" />
    <button type="button" (click)="uploader.uploadAll()" [disabled]="!uploader.getNotUploadedItems().length">
      Upload
    </button>
  </div>

</div>

Now, It’s time to start the Angular 8 app to check out the File upload demo in the browser. Run the following command:

ng serve --open

Make sure your NODE server must be running to manage the backend.

When you upload the image from front-end you’ll see your image files are saving inside the backend > uploads folder.

Conclusion

In this Angular 8 tutorial, we barely scratched the surface related to file uploading in a Node application. There are various other methods available on the internet through which you can achieve file uploading task quickly. However, this tutorial is suitable for beginners developers. I hope this tutorial will surely help and you if you liked this tutorial, please consider sharing it with others.

Angular JS Development Company

If you’re finding AngularJS Development Company for consultation or Development, your search ends here at Data EximIT 

🔗 Click here to know more: AngularJS Development