Angular ngFor directive - Bind dynamic data to SELECT Dropdown using Web API in MVC 4

← PrevNext →

You can use an ngFor directive in Angular 4 to loop through an array of data and bind the data to an element in your application template. Here in this post I am sharing an example on how to extract data by consuming an Asp.Net Web API service and use the data to populate a SELECT Dropdown list using Angular 4 ngFor Directive.

Uisng Angular 4 With a SELECT DropDown List Element using Web API in MVC 4

The ngFor directive is a successor of ng-repeat directive in AngularJS. You can attach the ngFor directive to an element like this,

<div *ngFor='let bird of arrBirds'>
    <div>{{ bird.name }}</div>
</div>

The value bird inside *ngFor directive is a variable of an array named arrBirds, which I have declared in my component class. The array has a property called name with some values it.

export class AppComponent {
  arrBirds: any [] = [
    { name: 'Bells Sparrow' },
    { name: 'Mourning Dove'},
    { name: 'Bald Eagle' }
  ];
  
  ngOnInit () {
    );
  }
}

The output, in your browser, would be,

Bells Sparrow
Mourning Dove
Bald Eagle

Now, let’s see how we can add dynamic data (extracted from a Web API method) to an array and attach the array to a SELECT Dropdown list using the ngFor directive.

Create a Table in SQL Server

We need a database for the data. Create a table in SQL Server and few data to it.

CREATE TABLE [dbo].[Books](
    [BookID] [int] IDENTITY(1,1) NOT NULL,
    [BookName] [varchar](50) NULL,
    PRIMARY KEY CLUSTERED ( [BookID] ASC )
) ON [PRIMARY]

Web API (using MVC 4)

Next, create a Web API in Asp.Net. I have MVC 4 installed in my computer. You can use any other version.

Model Books.cs (C#)
using System;
namespace BooksApp.Models
{
    public class Books
    {
        public string BookName { get; set; }
    }
}
Model Books.vb (Vb.Net)
Imports System.Web

Namespace BooksApp.Models
    Public Class Books
        Public Property BookName() As String
            Get
                Return m_BookName
            End Get
            Set(value As String)
                m_BookName = value
            End Set
        End Property
        Private m_BookName As String
    End Class
End Namespace

Web API Controller

The Controller in this project has a single public method called Get(), which will handle the http request and return the list of books to the calling application.

BooksController.cs (C#)
using System;
using System.Collections.Generic;
using System.Net;
using System.Net.http;
using System.Web.http;

using BooksApp.Models;
using System.Data.SqlClient;

namespace BooksApp.Controllers
{
    public class BooksController : ApiController
    {
        // LIST OBJECT WILL HOLD AND RETURN A LIST OF BOOKS.
        List<Books> MyBooks = new List<Books>();

        // THE "GET" METHOD WILL RETURN ALL THE BOOKS IN THE TABLE.
        public IEnumerable<Books> Get()
        {
            string sConnString = "Data Source=DNA;Persist Security Info=False;" +
                "Initial Catalog=DNA_Classified;User Id=sa;Password=;Connect Timeout=30;";

            SqlConnection myConn = new SqlConnection(sConnString);

            // THE SQL QUERY TO GET THE BOOKS FROM THE TABLE.
            SqlCommand objComm = new SqlCommand("SELECT *FROM dbo.Books", myConn);
            myConn.Open();

            SqlDataReader reader = objComm.ExecuteReader();

            // POPULATE THE LIST WITH DATA.
            while (reader.Read())
            {
                MyBooks.Add(new Books
                {
                    BookName = reader["BookName"].ToString()
                });
            }
            myConn.Close();

            return MyBooks;         // RETURN THE LIST.
        }
    }
}
BooksController.vb (Vb.Net)
Option Explicit On

Imports System.Net.http
Imports System.Web.http

Imports System.Data.SqlClient
Imports BooksApp.BooksApp.Models

Namespace BooksApp
    Public Class BooksController
        Inherits ApiController

        ' LIST OBJECT WILL HOLD AND RETURN A LIST OF BOOKS.
        Dim MyBooks As New List(Of Books)()

        ' THE "GET" METHOD WILL RETURN ALL THE BOOKS IN THE TABLE.
        Public Function [Get]() As IEnumerable(Of Books)
            Dim sConnString As String = "Data Source=DNA;Persist Security Info=False;" & _
                "Initial Catalog=DNA_Classified;User Id=sa;Password=;Connect Timeout=30;"

            Dim myConn As New SqlConnection(sConnString)

            ' THE SQL QUERY TO GET THE BOOKS FROM THE TABLE.
            Dim objComm As New SqlCommand("SELECT *FROM dbo.Books", myConn)

            myConn.Open()

            Dim reader As SqlDataReader = objComm.ExecuteReader()

            ' POPULATE THE LIST WITH DATA.
            While reader.Read()
                MyBooks.Add(New Books() With { _
                    .BookName = reader("BookName").ToString()
                 })
            End While
            myConn.Close()

            Return MyBooks          ' FINALLY, RETURN THE LIST.
        End Function
    End Class
End Namespace

Run the API.

Create Angular 4 Project

Now, create a project using Angular CLI (Command Line Interface). Open the command prompt and go to the folder where you want to create the project and enter,

ng new angular-ngfor-example

Next, go to the folder.

cd angular-ngfor-example

Finally, launch the server.

ng serve --open

Import HttpClientModule to the Project

To consume the Web API services in my Angular app, I am using the new HttpClient Service in my application. This service was first introduced in Angular 4.3 and is included in the HttpClientModule. Therefore, I’ll first import the HttpClientModule in the app.module.ts file.

Along with HttpClientModule, I am also importing the FormModule. I have highlighted both the modules in the code below.

import { BrowserModule } from '@angular/platform-browser';
import { NgModule } from '@angular/core';
import { AppComponent } from './app.component';

import { HttpClientModule } from '@angular/common/https';
import { FormsModule } from '@angular/forms';

@NgModule({
  declarations: [
    AppComponent
  ],
  imports: [
    BrowserModule,
    HttpClientModule,
    FormsModule
  ],
  providers: [],
  bootstrap: [AppComponent]
})
export class AppModule { }

The FormModule in the above code, is necessary since I am using the ngModel directive for one way binding. See the application template (the markup) below.

After we have created the module, its time create the component.

The Application Component

Open app.component.ts file. Here we’ll import the HttpClient class, which will provide the necessary functions and properties to initiate http request and responses. I’ll import HttpErrorResponse class to handle errors. Finally, I’ll declare an array here, which will hold data extracted from the http response and attach the array to the SELECT Dropdown list using ngFor directive.

import { Component, OnInit } from '@angular/core';
import { HttpClient } from '@angular/common/https';
import { HttpErrorResponse } from '@angular/common/https/src/response';

@Component({
  selector: 'app-root',
  templateUrl: './app.component.html',
  styleUrls: ['./app.component.css']
})
export class AppComponent {
  title = 'Angular 4 ngFor Example with SELECT Dropdown List';

  constructor (private httpService: HttpClient) { }

  myBooks: string [];
  selected = null;		

  ngOnInit () {
    this.httpService.get('http://localhost:43487/api/books/').subscribe(
      data => {
        this.myBooks = data as string [];		// FILL THE ARRAY WITH DATA.
      },
      (err: HttpErrorResponse) => {
        console.log (err.message);
      }
    );
  }
}
The Application Template

I’ll now add a SELECT Dropdown list element to my project template and attach the array (myBooks) to the element using ngFor directive.

<div style="text-align:center;width:500px;">
    <h1>
        {{title}}!
    </h1>

    <div style="float:left;padding:10px;margin:0 auto;" *ngIf="myBooks">
        <select [(ngModel)]="selected">
            <option *ngFor="let book of myBooks" [(ngValue)]="book.BookName">{{book.BookName}}</option>
        </select>

        <p>{{ selected }}</p>
    </div>
</div>

You can style it if you want using inline CSS or add some classes and properties in the app.component.css file.

Other than ngFor, I am using three other directives in my application template. The first is *ngIf directive to check if myBooks exists. The second directive is ngModel, to bind the selected value (in the SELECT Dropdown list) with a <p> element.

The third and fourth directives are the ngFor and ngValue with the <option> tag.

<option *ngFor="let book of myBooks" [(ngValue)]="book.BookName">{{book.BookName}}</option>

The ngValue directive is an alternative to the value property. I could have used the value to show the items in the Dropdown list. It works fine.

<option *ngFor="let book of myBooks" value="book.BookName">{{book.BookName}}</option>

However, with the value property, I cannot bind the selected value (using ngModel) to the <p> element properly. The ngValue directive solves the problem.

This post here may also be useful.

That’s it. I have explained about Error Handling in Angular 4 in my previous post, since I have applied error handler in the component above.

Conclusion

Well, binding dynamic data (using Web API), to a SELECT Dropdown list in Angular 4 is very simple. You can use a JSON array for your exmaple. I have shared a similar example before and you should read it too.

I have also explained two simple examples here on how to use Angular 4 ngFor directive with an HTML element to show data, extracted from an array. The ngFor loops through a list of items in array and displays it.

Along with this, I have explained one way binding using ngModel directive. I have shown you how to attach the directive with the SELECT element and display the selected value to another element.

Thanks for reading.

← PreviousNext →