Home JavaScript

AngularJS CRUD Example with Material Design – Step by Step Guide!


Previously, we learned how to create, read, update and delete database records with our React CRUD Tutorial. Today, we will learn how to do the same CRUD operations with AngularJS, Angular Material and REST API.

Contents of this tutorial include:

1.0 Tutorial Overview
2.0 Program Output - AngularJS CRUD Example
3.0 Set Up The REST API

4.0 Basic Files & Folders
4.1 File Structure
4.2 Create index.html file
4.3 Include Angular Material, Roboto Font and Custom CSS
4.4 AngularJS and Angular Material JavaScript
4.5 Custom JavaScript
4.6 Place AngularJS app container
4.7 Output

5.0 How To Read JSON Data Using AngularJS?
5.1 Create Template for products list
5.2 Create "products" controller
5.3 Create "products" factory
5.4 Output

6.0 How To Create or 6Insert Data Using AngularJS?
6.1 Add "create" product button
6.2 Show "create product" form in dialog box
6.3 Create dialog controller
6.4 Create "create_product" HTML form template
6.5 Add "createProduct" method in controller
6.6 Clear form contents
6.7 Show messages to user
6.8 Add "createProduct" method in factory
6.9 Output

7.0 How To Read One Data Using AngularJS?
7.1 Add "Read One" button in products list
7.2 Show product information in dialog box
7.3 Create "read_one_product.template.html" file
7.4 Add "readOneProduct" method in factory
7.5 Output

8.0 How To Update Data Using AngularJS?
8.1 Add "Edit" button in products list
8.2 Show editable product information in dialog box
8.3 Create "update_product.template.html" file
8.4 Add "updateProduct" method in controller
8.5 Add "updateProduct" method in factory
8.6 Output

9.0 How To Delete Data Using AngularJS?
9.1 Add "delete" button in products list
9.2 Ask user to confirm product deletion
9.3 Add "deleteProduct" function in controller
9.4 Add "deleteProduct" function in factory
9.5 Output

10.0 How To Search Data Using AngularJS?
10.1 Allow users to type search keywords
10.2 Add "searchProducts" function in controller
10.3 Add "searchProducts" function in factory
10.4 Output

11.0 How To Run The Source Code?
12.0 Download LEVEL 1 Source Code
13.0 Download LEVEL 2 Source Code
14.0 Download ALL LEVELS

15.0 What’s Next?
16.0 Related Tutorials
17.0 Notes

1.0 Tutorial Overview

What is AngularJS? It is one of the leading framework for building large JavaScript applications that are easy to maintain.

It makes the development faster because we can implement useful concepts like dependency injection, two-way data binding, reusable code and unit testing.

This tutorial will focus on creating, reading, updating, deleting and searching database records. We will do it using AngularJS and Angular Material as it's user interface component.

JSON data will be handled by the REST API built using PHP.

2.0 Program Output - AngularJS CRUD Example

2.1 LEVEL 1 Source Code Output


2.2 LEVEL 2 Source Code Output


The LEVEL 2 source code output proves that you can add and customize more features. It’s easier and faster if you will learn by following our tutorial below.

Downloading our source codes is your huge advantage as well. For now, let’s proceed to the step by step tutorial of our LEVEL 1 source code. Enjoy!

3.0 Set Up The REST API

In this tutorial, we are going to use a REST API built with PHP.

We did not include REST API source code because we want you to focus on learning how to code with AngularJS, not PHP.

But the good news is, we made a separate tutorial about how to build a simple REST API with PHP. Click here to learn the step-by-step PHP REST API tutorial.

I highly recommend learning our REST API tutorial first. This is because we are going to use that API for the rest of this tutorial.

But if you already have your own REST API that will work with this tutorial, that’s okay as well.

In my case, one example where I can access the REST API is: http://localhost/api/product/read.php

That link will show me the list of products from the database, in JSON format. It looks like the following screenshot.

The data above will be consumed by our AngularJS app. The list of products will be displayed in the page with buttons like "Read One", "Update" and "Delete". You will see it in the "How To Read JSON Data Using AngularJS?" section of this tutorial.

By the way, I'm using a Chrome extension called JSONView to make the JSON data readable in the browser.

4.0 Basic Files & Folders

4.1 File Structure

At the end of this tutorial, we will have the following file structure.
├─ app/
├─── assets/
├────── css/
├───────── custom.css
├─── products/
├────── create_product.template.html
├────── products.controller.js
├────── products.factory.js
├────── read_one_product.template.html
├────── read_products.template.html
├────── update_product.template.html
├─── app.js
├─ index.html

4.2 Create index.html file

Create index.html file. Open that file and put the following basic HTML code.

<!DOCTYPE html>
<html>
<head>

    <meta charset="utf-8">
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <meta name="viewport" content="width=device-width, initial-scale=1">

    <title>Read Products</title>

</head>
<body>

<!-- app container will be here -->

</body>
</html>

4.3 Include Angular Material, Roboto Font and Custom CSS

We are going to use CSS files from Google CDN. Place the following code inside "head" tag, under "title" tag of the previous section.

<!-- angular material style sheet -->
<link rel="stylesheet" href="http://ajax.googleapis.com/ajax/libs/angular_material/1.1.0/angular-material.min.css">

<!-- roboto font -->
<link rel="stylesheet" href="https://fonts.googleapis.com/css?family=Roboto:300,400,500,700,400italic">

<!-- include custom CSS -->
<link rel="stylesheet" href="app/assets/css/custom.css" />

Our "custom.css" file does not exist yet so we have to create it. We will put some CSS as well to style some parts of our application.

  1. Create "app" folder.
  2. Inside "app" folder, create "assets" folder.
  3. Inside "assets" folder, create "css" folder.
  4. Inside "css" folder, create "custom.css" file.
  5. Open "custom.css" file and place the following code.
md-dialog{ width:50%; }
.m-20px-0{ margin:20px 0; }
.m-b-20px{ margin-bottom:20px; }
.m-b-0px{ margin-bottom:0px; }
.md-info{ background-color:#2196F3 !important; color:#ffffff !important; }
.md-danger{ background-color:#D32F2F !important; color:#ffffff !important; }
.w-5-pct{ width:5%; }
.w-10-pct{ width:10%; }
.w-20-pct{ width:20%; }
.w-30-pct{ width:30%; }
.w-35-pct{ width:35%; }
.w-40-pct{ width:40%; }
.w-50-pct{ width:50%; }
.w-60-pct{ width:60%; }
.w-70-pct{ width:70%; }
.w-80-pct{ width:80%; }
.w-90-pct{ width:90%; }
.w-100-pct{ width:100%; }
.t-a-c{ text-align:center; }
.t-a-l{ text-align:left; }
.margin-bottom-1em{ margin-bottom:1em; }

4.4 AngularJS and Angular Material JavaScript

We are going to use AngularJS JavaScript files from Google CDN. Place the following code before the closing "body" tag.

<!-- include angular js -->
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.1/angular.min.js"></script>

<!-- needed for angular material -->
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-animate.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-aria.min.js"></script>
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.5.5/angular-messages.min.js"></script>

<!-- angular material Library -->
<script src="http://ajax.googleapis.com/ajax/libs/angular_material/1.1.0/angular-material.min.js"></script>

4.5 Custom JavaScript

Place the following code after the previous section's code.

<!-- app -->
<script type="text/javascript" src="app/app.js"></script>

<!-- products controller -->
<script type="text/javascript" src="app/products/products.controller.js"></script>

<!-- products factory -->
<script type="text/javascript" src="app/products/products.factory.js"></script>

The JavaScript files above does not exist yet so we will create it.

  1. Open "app" folder.
  2. Inside "app" folder, create "app.js" file.
  3. Inside "app" folder again, create "products" folder.
  4. Inside "products" folder, create "products.controller.js" and "products.factory.js" files.

Open "app.js" file and place the following code.

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

We added 'ngMaterial' parameter to enable our Angular Material user interface. We will explain and place AngularJS codes inside "products.controller.js" and "products.factor.js" files as we progress in this tutorial.

4.6 Place AngularJS app container

The "read_products.template.html" will hold the template for displaying list of products.

Find

<!-- app container will be here -->

in index.html and replace it with the following code.

<!-- container of our app -->
<div class="container" ng-app="myApp">

    <!-- read products template -->
    <ng-include src="'./app/products/read_products.template.html'"></ng-include>

</div> <!-- end container -->

The "read_products.template.html" file does not exist yet so we will create it.

  1. Open "app" folder.
  2. Inside "app" folder, open "products" folder.
  3. Inside "products" folder, create "read_products.template.html" file.

4.7 Output

After doing all the steps above. The output is a blank page. Yes, a blank page for now. But for sure, we will see something here after you complete the next section.

5.0 How To Read JSON Data Using AngularJS?

5.1 Template for products list

Open "read_products.template.html" file and place the following code.

<div layout="row" ng-controller="productsController" ng-cloak>
    <div flex="10"></div>

    <div flex="80" class='m-20px-0'>

        <!-- page title & 'create product' button -->
        <md-toolbar class="md-hue-2">
            <div class="md-toolbar-tools">
                <!-- page title -->
                <div flex md-truncate>
                    <h3 class="md-headline">Products</h3>
                </div>

                <!-- 'create' product button will be here -->
            </div>
        </md-toolbar>

        <!-- 'search' bar will be here -->

        <md-content flex>
            <!-- show product record list -->
            <md-list ng-init="readProducts()">
                <md-list-item class="md-3-line" ng-repeat="product in products">

                    <!-- product information -->
                    <div class="md-list-item-text">
                        <h3>{{product.name}}</h3>
                        <h4>{{product.description}}</h4>
                        <p>${{product.price}}</p>
                    </div>

                    <!-- 'read one', 'edit' and 'delete' buttons -->
                    <div class="md-secondary-container">
						<!-- 'read one' button will be here -->
						<!-- 'edit' button will be here -->
						<!-- 'delete' button will be here -->
                    </div>
                    <md-divider ng-if="!$last"></md-divider>
                </md-list-item>
            </md-list>
        </md-content>
    </div>

    <div flex="10"></div>
</div> <!-- end row -->

5.2 Create "products" controller

  1. Open "app" folder.
  2. Inside "app" folder, open "products" folder.
  3. Inside "products" folder, create "products.controller.js" file.
  4. Open "products.controller.js" file and place the following code.
app.controller('productsController', function($scope, $mdDialog, $mdToast, productsFactory){

	// read products
	$scope.readProducts = function(){

		// use products factory
		productsFactory.readProducts().then(function successCallback(response){
			$scope.products = response.data.records;
		}, function errorCallback(response){
			$scope.showToast("Unable to read record.");
		});

	}
	
	// showCreateProductForm will be here
	
	// DialogController will be here
});

5.3 Create "products" factory

Why do we use "factory" in AngularJS? We use it to make the code reusable.

Methods in factories can be used in different controllers or parts of your application. If there will be a need for change, you don't have to go and change several parts of the application that uses the same code.

  1. Open "products.factory.js" file.
  2. Create "products.factory.js" file and place the following code.
app.factory("productsFactory", function($http){

    var factory = {};

    // read all products
    factory.readProducts = function(){
        return $http({
            method: 'GET',
            url: 'http://localhost/api/product/read.php'
        });
    };
	
	// createProduct will be here
	
	return factory;
});

5.4 Output

You should see the list of products. Each row should have product name, description and price.

6.0 How To Create or Insert Data Using AngularJS?

6.1 Add "create" product button

We need this button to show a form where user can enter new product information.

  1. Open "read_products.template.html".
  2. Find
    <!-- 'create' product button will be here -->
  3. Replace it with the following code.
<!-- button for creating product -->
<md-button class="md-raised" ng-click="showCreateProductForm()">Create</md-button>

6.2 Show "create product" form in dialog box

  1. Open "products.controller.js" file.
  2. Find "// showCreateProductForm will be here" and replace it with the following code.
// show 'create product form' in dialog box
$scope.showCreateProductForm = function(event){

	$mdDialog.show({
		controller: DialogController,
		templateUrl: './app/products/create_product.template.html',
		parent: angular.element(document.body),
		clickOutsideToClose: true,
		scope: $scope,
		preserveScope: true,
		fullscreen: true // Only for -xs, -sm breakpoints.
	});
}

// createProduct will be here

6.3 Create dialog controller

We are using Angular Material's dialog box above. Users may click the 'Cancel' button. We need a method for that.

  1. Open "products.controller.js".
  2. Find "// DialogController will be here" and replace it with the following code.
// methods for dialog box
function DialogController($scope, $mdDialog) {
	$scope.cancel = function() {
		$mdDialog.cancel();
	};
}

6.4 Create "create_product" HTML form template

Our dialog box loads an HTML temlate via "templateUrl" property.

  1. Open "app" folder.
  2. Inside "app" folder, open "products" folder.
  3. Inside "products" folder, create "create_product.template.html" file.
  4. Open "create_product.template.html" file and place the following code.
<md-dialog>
    <form ng-cloak>
        
        <md-toolbar>
            <div class="md-toolbar-tools">
                <h2>Create Product</h2>
            </div>
        </md-toolbar>

        <md-dialog-content>
            <div class="md-dialog-content">

				<!-- we are using ng-model to bind this view and the 'product model -->
                <md-input-container class="md-block">
                    <label>Name</label>
                    <input ng-model="name">
                </md-input-container>

                <md-input-container class="md-block">
                    <label>Description</label>
                    <input ng-model="description">
                </md-input-container>

                <md-input-container class="md-block">
                    <label>Price</label>
                    <input ng-model="price">
                </md-input-container>

            </div>
        </md-dialog-content>

        <md-dialog-actions layout="row">
            <md-button ng-click="cancel()">Cancel</md-button>
            <md-button ng-click="createProduct()" class="md-primary">Create</md-button>
        </md-dialog-actions>
    </form>
</md-dialog>

6.5 Add "createProduct" method in controller

  1. Open "products.controller.js".
  2. Find "// createProduct will be here" and replace it with the following code.
// create new product
$scope.createProduct = function(){

	productsFactory.createProduct($scope).then(function successCallback(response){

		// tell the user new product was created
		$scope.showToast(response.data.message);

		// refresh the list
		$scope.readProducts();

		// close dialog
		$scope.cancel();

		// remove form values
		$scope.clearProductForm();

	}, function errorCallback(response){
		$scope.showToast("Unable to create record.");
	});
}

// readOneProduct will be here

6.6 Clear form contents

We need clearProductForm to clear form values.

Place the following code after the previous section's code.

// clear variable / form values
$scope.clearProductForm = function(){
	$scope.id = "";
	$scope.name = "";
	$scope.description = "";
	$scope.price = "";
}

6.7 Show messages to user

We are using "toasts" to show messages to users.

Place the following code after the previous section's code.

// show toast message
$scope.showToast = function(message){
	$mdToast.show(
		$mdToast.simple()
			.textContent(message)
			.hideDelay(3000)
			.position("top right")
	);
}

6.8 Add "createProduct" method in factory

  1. Open "products.factory.js" file.
  2. Find "// createProduct will be here" and replace it with the following code.
// create product
factory.createProduct = function($scope){
	return $http({
		method: 'POST',
		data: {
			'name' : $scope.name,
			'description' : $scope.description,
			'price' : $scope.price,
			'category_id' : 1
		},
		url: 'http://localhost/api/product/create.php'
	});
};

// readOneProduct will be here

6.9 Output

You should see a "create" button on the upper right corner of the page. Once this button is clicked, a dialog box with a "create product" form should appear.

7.0 How To Read One Data Using AngularJS?

7.1 Put "Read One" button in products list

  1. Open "read_products.template.html" file.
  2. Find
    <!-- 'read one' button will be here -->

    and replace it with the following code.

<md-button class="md-raised md-info" ng-click="readOneProduct(product.id)">Read One</md-button>

7.2 Show product information in dialog box

If the user click "read one" button, a dialog box will appear with the product information.

  1. Open "products.controller.js" file.
  2. Find "// readOneProduct will be here" and replace it with the following code.
// retrieve record to fill out the form
$scope.readOneProduct = function(id){

	// get product to be edited
	productsFactory.readOneProduct(id).then(function successCallback(response){

		// put the values in form
		$scope.id = response.data.id;
		$scope.name = response.data.name;
		$scope.description = response.data.description;
		$scope.price = response.data.price;

		$mdDialog.show({
			controller: DialogController,
			templateUrl: './app/products/read_one_product.template.html',
			parent: angular.element(document.body),
			clickOutsideToClose: true,
			scope: $scope,
			preserveScope: true,
			fullscreen: true
		}).then(
			function(){},

			// user clicked 'Cancel'
			function() {
				// clear modal content
				$scope.clearProductForm();
			}
		);

	}, function errorCallback(response){
		$scope.showToast("Unable to retrieve record.");
	});

}

// showUpdateProductForm will be here

7.3 Create "read_one_product.template.html" file

The dialog box need an HTML template with product information.

  1. Open "products" folder.
  2. Inside "products" folder, create "read_one_product.template.html" file and place the following code.
<md-dialog>
    <form ng-cloak>

        <!-- dialog box title -->
        <md-toolbar>
            <div class="md-toolbar-tools">
                <h2>Read One Product</h2>
            </div>
        </md-toolbar>

        <md-dialog-content>
            <div class="md-dialog-content">

                <!-- display product information -->
                <md-input-container class="md-block">
                    <label>Name</label>
                    <input ng-model="name" disabled>
                </md-input-container>

                <md-input-container class="md-block">
                    <label>Description</label>
                    <input ng-model="description" disabled>
                </md-input-container>

                <md-input-container class="md-block">
                    <label>Price</label>
                    <input ng-model="price" disabled>
                </md-input-container>

            </div>
        </md-dialog-content>

        <!-- button to close the dialog box -->
        <md-dialog-actions layout="row">
            <md-button ng-click="cancel()">Cancel</md-button>
        </md-dialog-actions>
    </form>
</md-dialog>

7.4 Add "readOneProduct" method in factory

We will get the product information from the API.

  1. Open "products.factory.js" file.
  2. Find "// readOneProduct will be here" and replace it with the following code.
// read one product
factory.readOneProduct = function(id){
	return $http({
		method: 'GET',
		url: 'http://localhost/api/product/read_one.php?id=' + id
	});
};

// updateProduct will be here

7.5 Output

You should see a "read one" button in the product list. Once user clicks this, a dialog box will appear with a product information.

8.0 How To Update Data Using AngularJS?

8.1 Put "Edit" button in products list

  1. Open "read_products.template.html" file.
  2. Find
    <!-- 'edit' button will be here -->

    and replace it with the following code.

<md-button class="md-raised md-primary" ng-click="showUpdateProductForm(product.id)">Edit</md-button>

8.2 Show editable product information in dialog box

  1. Open "products.controller.js" file.
  2. Find "// showUpdateProductForm will be here" and replace it with the following code.
// retrieve record to fill out the form
$scope.showUpdateProductForm = function(id){

	// get product to be edited
	productsFactory.readOneProduct(id).then(function successCallback(response){

		// put the values in form
		$scope.id = response.data.id;
		$scope.name = response.data.name;
		$scope.description = response.data.description;
		$scope.price = response.data.price;

		$mdDialog.show({
			controller: DialogController,
			templateUrl: './app/products/update_product.template.html',
			parent: angular.element(document.body),
			targetEvent: event,
			clickOutsideToClose: true,
			scope: $scope,
			preserveScope: true,
			fullscreen: true
		}).then(
			function(){},

			// user clicked 'Cancel'
			function() {
				// clear modal content
				$scope.clearProductForm();
			}
		);

	}, function errorCallback(response){
		$scope.showToast("Unable to retrieve record.");
	});

}

// updateProduct will be here

8.3 Create "update_product.template.html" file

The dialog box need an HTML template with product information.

  1. Open "products" folder.
  2. Inside "products" folder, create "update_product.template.html" file and place the following code.
<md-dialog>
    <form ng-cloak>

        <!-- dialog box title -->
        <md-toolbar>
            <div class="md-toolbar-tools">
                <h2>Update Product</h2>
            </div>
        </md-toolbar>

        <md-dialog-content>
            <div class="md-dialog-content">

                <!-- dialog box input fields with editable product information -->
                <md-input-container class="md-block">
                    <label>Name</label>
                    <input ng-model="name">
                </md-input-container>

                <md-input-container class="md-block">
                    <label>Description</label>
                    <input ng-model="description">
                </md-input-container>

                <md-input-container class="md-block">
                    <label>Price</label>
                    <input ng-model="price">
                </md-input-container>

            </div>
        </md-dialog-content>

        <!-- dialog box buttons -->
        <md-dialog-actions layout="row">
            <md-button ng-click="cancel()">Cancel</md-button>
            <md-button ng-click="updateProduct()" class="md-primary">Update</md-button>
        </md-dialog-actions>
    </form>
</md-dialog>

8.4 Put "updateProduct" method in controller

If the user click the "update" button in the dialog box, we will send the udpated data to the API.

  1. Open "products.controller.js" file.
  2. Find "// updateProduct will be here" and replace it with the following code.
// update product record / save changes
$scope.updateProduct = function(){

	productsFactory.updateProduct($scope).then(function successCallback(response){

		// tell the user product record was updated
		$scope.showToast(response.data.message);

		// refresh the product list
		$scope.readProducts();

		// close dialog
		$scope.cancel();

		// clear modal content
		$scope.clearProductForm();

	},
	function errorCallback(response) {
		$scope.showToast("Unable to update record.");
	});

}

// confirmDeleteProduct will be here

8.5 Put "updateProduct" method in factory

The factory will help us send data to API.

  1. Open "products.factory.js" file.
  2. Find "// updateProduct will be here" and replace it with the following code.
// update product
factory.updateProduct = function($scope){

	return $http({
		method: 'POST',
		data: {
			'id' : $scope.id,
			'name' : $scope.name,
			'description' : $scope.description,
			'price' : $scope.price,
			'category_id' : 1
		},
		url: 'http://localhost/api/product/update.php'
	});
};

// deleteProduct will be here

8.6 Output

You should see the "Edit" button in the products list. When this button is clicked, a dialog box with "udpate product" form will appear.

The form contains the editable product information.

9.0 How To Delete Data Using AngularJS?

9.1 Put "delete" button in products list

  1. Open "read_products.template.html" file.
  2. Find
    <!-- 'delete' button will be here -->

    and replace it with the following code.

<md-button class="md-raised md-danger" ng-click="confirmDeleteProduct($event, product.id)">Delete</md-button>

9.2 Ask user to confirm product deletion

  1. Open "products.controller.js" file.
  2. Find "// confirmDeleteProduct will be here" and replace it with the following code.
// cofirm product deletion
$scope.confirmDeleteProduct = function(event, id){

	// set id of record to delete
	$scope.id = id;

	// dialog settings
	var confirm = $mdDialog.confirm()
		.title('Are you sure?')
		.textContent('Product will be deleted.')
		.targetEvent(event)
		.ok('Yes')
		.cancel('No');

	// show dialog
	$mdDialog.show(confirm).then(
		// 'Yes' button
		function() {
			// if user clicked 'Yes', delete product record
			$scope.deleteProduct();
		},

		// 'No' button
		function() {
			// hide dialog
		}
	);
}

9.3 Put "deleteProduct" function in controller

If the user click the 'Yes' button, our app will delete the record.

Place the following code after the previous section's code.

// delete product
$scope.deleteProduct = function(){

	productsFactory.deleteProduct($scope.id).then(function successCallback(response){

		// tell the user product was deleted
		$scope.showToast(response.data.message);

		// refresh the list
		$scope.readProducts();

	}, function errorCallback(response){
		$scope.showToast("Unable to delete record.");
	});

}

// searchProducts will be here

9.4 Put "deleteProduct" function in factory

The factory will help us send data to API.

  1. Open "products.factory.js" file.
  2. Find "// deleteProduct will be here" and replace it with the following code.
// delete product
factory.deleteProduct = function(id){
	return $http({
		method: 'POST',
		data: { 'id' : id },
		url: 'http://localhost/api/product/delete.php'
	});
};

// searchProducts will be here

9.5 Output

You should see the "Delete" button in products list. When a user click this button, a dialog box will appear asking the confirmation to delete the record.

10.0 How To Search Data Using AngularJS?

This feature is part of LEVEL 2 source code. We did not use "filter" to search product records. We search the records with the help of API.

10.1 Allow users to type search keywords

  1. Open "read_products.template.html" file.
  2. Find
    <!-- 'search' bar will be here -->

    and replace it with the following code.

<!-- used for searching products in api -->
<md-input-container class="md-block m-b-0px">
	<form ng-submit="searchProducts()">
		<label>Search products...</label>
		<input ng-model="product_search_keywords">
	</form>
</md-input-container>

10.2 Add "searchProducts" function in controller

  1. Open "products.controller.js" file.
  2. Find "// searchProducts will be here" and replace it with the following code.
// search products
$scope.searchProducts = function(){

	// use products factory
	productsFactory.searchProducts($scope.product_search_keywords).then(function successCallback(response){
		$scope.products = response.data.records;
	}, function errorCallback(response){
		$scope.showToast("Unable to read record.");
	});
}

10.3 Add "searchProducts" function in factory

The factory will help us read records based on search keywords.

  1. Open "products.factory.js" file.
  2. Find "// searchProducts will be here" and replace it with the following code.
// search all products
factory.searchProducts = function(keywords){
	return $http({
		method: 'GET',
		url: 'http://localhost/api/product/search.php?s=' + keywords
	});
};

10.4 Output

You should see the "search" bar above products list. Once user type a keyword and press the "enter" key, search results must be seen.

11.0 How To Run The Source Code?

We highly recommend for you to follow and study our well-detailed, step-by-step tutorial above first. Nothing beats experience when it comes to learning.

But we believe you will learn faster if you'll see the final source code as well. We consider it as your additional guide.

Imagine the value or skill upgrade it can bring you. The additional income you can get from your work, projects or business. The precious time you save. Isn't that what you want?

By now, you need to download our source codes. To do it, use any download buttons in the next few sections below.

Once you downloaded the source codes, here's how you can run it.

  1. Extract the files to your server directory.
  2. Set up the "api" by following the README.txt inside the "api" folder.
  3. Open your browser and run index.html
  4. If you can see the list of products, it means your set up is correct.

12.0 Download LEVEL 1 Source Code

FEATURES LEVEL 1
Create product YES
Read product YES
Read one product YES
Update product YES
Delete product YES
Angular Material UI YES
PHP REST API source code YES
FREE email support for 3 months YES
Source code updates via email YES
Download Now

THANK YOU!

has been added to your cart!

Powered by Easy Digital Downloads

Thank you!

have been added to your cart!

Powered by Easy Digital Downloads

13.0 Download LEVEL 2 Source Code

FEATURES LEVEL 2
All features of LEVEL 1 YES
Search products YES
Pagination of products & search products YES
Create category YES
Read category YES
Read one category YES
Update category YES
Delete category YES
Search categories YES
Pagination of categories & search categories YES
Navigation bar YES
Use of AngularJS Directives YES
Use of AngularJS $q.all() YES
Use of AngularJS MainController YES
Use of Single pagination template File YES
Use of ng-class in navigation bar YES
FREE email support for 6 months YES
Download Now

THANK YOU!

has been added to your cart!

Powered by Easy Digital Downloads

Thank you!

have been added to your cart!

Powered by Easy Digital Downloads

14.0 Download ALL LEVELS

This means you will download the LEVEL 1, and 2 source codes in separate packages. Select "ALL LEVELS" and then click the “Download Now” button.

Download Now

THANK YOU!

has been added to your cart!

Powered by Easy Digital Downloads

Thank you!

have been added to your cart!

Powered by Easy Digital Downloads

Do you need more reasons to download it?

MORE REASONS TO DOWNLOAD THE CODE ALL
Use new skills for your multiple projects YES
Save huge amount of time learning AngularJS YES
Code examples are direct to the point YES
Well explained and commented source code YES
Fast and friendly email support YES
Free source code updates YES

15.0 What's Next?

Learn more JavaScript programming with our Angular 2 CRUD Tutorial - Step By Step Guide!

16.0 Related Tutorials

17.0 Some Notes

#1 Found An Issue?

If you found a problem with this code, we can solve it faster via Email or FB message, please send me a message via email mike@codeofaninja.com, or via our official Facebook page!

Please be more detailed about your issue. Best if you can provide an error message and your test or page URL. Thanks!

Please feel free to comment if you have any questions, suggestions, found something wrong or want to contribute to this code.

#2 Become a true Ninja!

We constantly add new tutorials and improve our existing tutorials and source codes. Be one of the first to know an update by subscribing to our FREE newsletter. Get a FREE EBOOK as well. CLICK HERE TO SUBSCRIBE FOR FREE!

#3 Thank You!

Thanks for reading our AngularJS CRUD Example with Material Design - Step by Step Guide!

139 replies
  1. IceTheMan
    IceTheMan says:

    well after running through the code up to where it should output something I find the code broken and just plain wrong. Using old form of Callbacks instead of promises and some unnecessary coding like a variable in the query when not needed for products. If you would actually be expecting someone to pay 45.00 I think that your code should be really a whole lot better than this,

    • Mike Dalisay
      Mike Dalisay says:

      Hi @IceTheMan:disqus, thanks for taking the time to comment, I truly appreciate it! Some questions though:

      1. What part of the tutorial the code is broken?
      2. What are those old form of callbacks and unnecessary variables?

      I just want to emphasize that this tutorial is for beginners so we made it super simple and easy to understand. I’d love to hear more of your thoughts so we can correct anything that is wrong. Thanks for helping us improve this tutorial!

      • Darren du Preez
        Darren du Preez says:

        yes i also find this code broken ?
        PHP Deprecated: Automatically populating $HTTP_RAW_POST_DATA is deprecated and will be removed in a future version

        what error i am getting, i am willing to pay for this course but if i see errors then i get worried

        • Mike Dalisay
          Mike Dalisay says:

          Hello @darrendupreez:disqus, thanks for your interest in this code. About your issue, we are unable to replicate it. Which part of the code did you see it and what is your PHP version? Would you provide a screenshot of the error you are facing?

          • Darren du Preez
            Darren du Preez says:

            Hi i have send you a FB message on the bug fix for new PHP versions as // get id of product to be edited
            $data = json_decode(file_get_contents(“php://input”)); this is outdated

        • Mike Dalisay
          Mike Dalisay says:

          Based from our FB conversation: It looks like you are using a GET request. You should follow what is in the tutorial so you won’t have a problem.

          Also, you are using $_REQUEST[‘name’] in the receiving PHP file where you should use $data->name;

          Please make sure that your PHP version is PHP 5.4+ and your JSON extension is enabled.

    • Mike Dalisay
      Mike Dalisay says:

      Hello @NatuAltermaxMyers:disqus, thanks for your comments, we appreciate it! About your concern, you asked:

      Q: Is this worth getting?
      A: It will really depend on you. If you need to use this kind of source code example for your project, it will be a very good place to start with. The code is well tested and working here at my end (see output screenshot slideshow above as well). Several people already bought this source code without having any issues. I’m ready to help you if you found one that you cannot solve, I reply usually within 12-24 hours.

      Q: Why can’t it be partially free so we can determine if the code is good?
      A: The source code is partially free through the tutorial. If you can follow the step by step tutorial, you will get the LEVEL 1 source code for free. We encourage people to follow the tutorial so that they can experience how the source code is done and so they will learn more and won’t take it for granted.

      Q: The comments aren’t good?
      A: You cannot say that the comments aren’t good because I answered all their comments with proof and I asked for more details. If they don’t answer my questions about why and how they get an issue, it means their issue is invalid. Reasons can be they don’t follow the tutorial up to the end, they are not yet capable to understand this kind of tutorial, or they don’t ask the right questions.

  2. iqbal malik
    iqbal malik says:

    Hello to everyone
    i follow this tutorial but i got error message and nothing to display..
    only table heading and add new product symbol is showing.. My Error is

    Error: JSON.parse: unexpected character at line 1 column 1 of the JSON data
    wc@http://localhost/angularjs_crud_level1/libs/js/angular.min.js:16:457
    cc@http://localhost/angularjs_crud_level1/libs/js/angular.min.js:88:468
    hd/<@http://localhost/angularjs_crud_level1/libs/js/angular.min.js:89:378
    n@http://localhost/angularjs_crud_level1/libs/js/angular.min.js:7:353
    hd@http://localhost/angularjs_crud_level1/libs/js/angular.min.js:89:360
    c@http://localhost/angularjs_crud_level1/libs/js/angular.min.js:91:102
    e/<@http://localhost/angularjs_crud_level1/libs/js/angular.min.js:126:404
    uf/this.$get</m.prototype.$eval@http://localhost/angularjs_crud_level1/libs/js/angular.min.js:141:43
    uf/this.$get</m.prototype.$digest@http://localhost/angularjs_crud_level1/libs/js/angular.min.js:138:132
    uf/this.$get</m.prototype.$apply@http://localhost/angularjs_crud_level1/libs/js/angular.min.js:141:339
    g@http://localhost/angularjs_crud_level1/libs/js/angular.min.js:94:137
    t@http://localhost/angularjs_crud_level1/libs/js/angular.min.js:98:260
    fg/</u.onload@http://localhost/angularjs_crud_level1/libs/js/angular.min.js:99:297

    Can anyone Help plz…

  3. gautam
    gautam says:

    hi mike,

    as you have explained , i make it and working, but only view, search and delete works perfect, but insert/update not working. popup not appearing on when i clicking on add button,

    please help

  4. forex maniac
    forex maniac says:

    i get an error :
    Fatal error: Call to undefined method Product::readAll() in …..read_products.php on line 14
    what is wrong with this part of code?

  5. hamza nouasri
    hamza nouasri says:

    Hi, I have a problem with this code in step 7.8 when I click on the button the interface of Create New Product does not show.
    thank you in advance.

  6. Fabián Chinchilla
    Fabián Chinchilla says:

    Ready Level 1, very well tutorial, is difficult if you do not have a basic knowledge of AngularJS and PDO,
    But if you investigate a little about these issues will be very easy

  7. ali nouasri
    ali nouasri says:

    Hellow Mike, I find this problem: call to undefined method Product::create() in c:xammphtdocsaboudcreate_product.php line 17

    and the list of products does not show in step 8.5

    thanks sir

    • Mike Dalisay
      Mike Dalisay says:

      Hello @ali, please make sure you added the code in section 7.9 to your objects/product.php

      About your second concern, please try to right click your browser > inspect element > console and tell me what error message do you see. Thank!

  8. Lulberla
    Lulberla says:

    I’m considering buying level2 and level3 so that i could learn how to do angular CRUD for my own learning project. however if there is a tutorial for these 2 levels, it will be more better for me to learn. As i’m looking for more features such as sorting,option to show X amount of entries in a table and etc, could you email me so that we could discuss more about this.

  9. Riec Engelhardt
    Riec Engelhardt says:

    Hello, thanks for the tutorial. great work. I have a problem that mine won’t edit. Its gives me the error of : unable to retrieve record. Help pls?

  10. Riec Engelhardt
    Riec Engelhardt says:

    Hello Mike, Thanks for the reply. I have just bought all the levels of source code, but did not receive no download link. please send mi the link so I can download what I paid for.
    This is the transaction ID : 52K24644XH413271R

  11. Mashumba
    Mashumba says:

    Really really cool. Best tut I have ever come across. Just to add that in section 7.8 PHP code to create a new record, include_once ‘objects/product.php’; has been omitted, causing a call to undefined method error.
    If anyone encountered this just add include_once ‘objects/product.php’; in create_product.php.

    • Mike Dalisay
      Mike Dalisay says:

      Hello @disqus_ugKnxClbec:disqus, thanks for the kind words! Thanks for the tip as well, I updated the blog post above.

      The following code has been added in section 7.8 above.


      include_once 'objects/product.php';
      $product = new Product($db);

  12. Bora eresici
    Bora eresici says:

    hi,
    cool works. Thank you for sharing

    I need add a 2. products and collapse /expand columns or different page designs for viex because I have 45 columns :)

    How do I make these additions? or do you make this changing?

    I think;
    CategoryA -> CategoryA1
    CateogryA1-> Product1
    CateogryA1-> Product2

  13. Stefan Aritonović
    Stefan Aritonović says:

    I have purchased PHP, MySQL and AngularJS CRUD LEVEL 3 Source Code. I tried to use it for my project – application for book evidence. Except I translated certain things on serbian I also changed table names and column names. After that I opened the application to see if everything is ok and saw that it couldn’t show any books from database, while categories are shown properly. Here are images to see what is the problem. I need to finish this project until tomorrow evening so I need your help because I don’t know how to solve this. I sent you the source code to your email. Thanks in advance.

  14. Mike Dalisay
    Mike Dalisay says:

    Hi @stefanaritonovi:disqus, glad it worked for you now!

    Who gave that points & said that comment? He maybe right but the purpose of our examples above is to give learners an example how to get started with AngularJS and not yet to be an expert of it.

    Also, for me it is acceptable to use only one JS file of AngularJS because the system is very small, it has only 1-2 objects.

    It is not a complete system with many components where you should really separate your JS files based on your objects.

    Soon I’m going to post a source code with 4-5 objects. There I made the JS and other files separated based on those objects. I’ll send you and all those subscribed a notification. :)

  15. John
    John says:

    Good morning. I’m at first level (7.10), but there is only one word “Products” on page and button in the right corner don’t works.
    Console says: TypeError: $(…).leanModal is not a function.
    Can anybody say whats’ wrong, please?

    p.s. Sorry for my English, if i made some grammar mistakes (i used google translate)

  16. Nestor Eduardo Iraheta Mazarie
    Nestor Eduardo Iraheta Mazarie says:

    Hi, I finished the CRUD and the issue is the output don’t show the record that added in the 3.2 point, I was write the code step by step correctly, can anybody guess what’s wrong please :(

  17. Guilherme
    Guilherme says:

    Hi Mike, thanks for your post! I appreciate your work!

    Two questions:

    I. This is in Angular 1.2.x, right? Can you show how to adapt for Angular 1.6.x (error .success is not a function, for example)?

    II. This pagination load the records from database on demand / per page? Or load all the records and only show per page?

    Sorry my bad english,

    Thanks again!

    • Mike Dalisay
      Mike Dalisay says:

      Hello @disqus_dZDJoWRNaA:disqus , you’re welcome! To answer your questions:

      I. Yes, this is AngularJS 1.2.x, we will update it to the latest version of AngularJS soon. Please subscribe so you will be notified. See: https://www.codeofaninja.com/subscribe

      II. Currently, it loads all records and then do the pagination. But the next update should load the requested page only (one at a time, from the database).

      • Guilherme
        Guilherme says:

        Hello Mike,

        Subscribed!

        I have already solved these two issues:

        I. I replaced success() and error() by .then()

        II. I followed this doc https://github.com/michaelbromley/angularUtils/tree/master/src/directives/pagination#working-with-asynchronous-data and created a way for pagination and search on demand from database.

        I can send it to you if you want.

        Now I need to develop the user authentication part, in a safe way. I do not know where to start =(

      • Jack Romanowicz
        Jack Romanowicz says:

        The fix for 1.6.1 is trivial: change “data” to “response.data” everywhere in index.php javascript. except in the function parameters. change the ‘success’ function definitions to ‘then’. Then remove the “data, status, headers, config” parameter lists in the success and error functions and replace them with only “response”. A sample is below.

        BTW, I chose to put the navigation buttons for pagination at the top of the table, as they disappear below the fold unpredictable depending on the amount of text in the item descriptions.

        Thanks for the tutorial & templates Mike!

        $http.post(‘read_one.php’, {
        ‘id’ : id
        })
        .then(function successCallback(response){

        // put the values in form
        $scope.id = response.data[0][“id”];
        $scope.name = response.data[0][“name”];
        $scope.description = response.data[0][“description”];
        $scope.price = response.data[0][“price”];

        // show modal
        $(‘#modal-product-form’).modal(‘open’);
        },
        (function errorCallback(response){
        Materialize.toast(‘Unable to retrieve record.’, 4000);
        }));

  18. Mike Dalisay
    Mike Dalisay says:

    Hello @baldwin. We’re unable to replicate the issue but we’ve update the tutorial to the latest version of AngularJS.

    To answer your question, modal must be initialized inside a script tag because it is JavaScript.

  19. Mike Dalisay
    Mike Dalisay says:

    Hi @baldwin, would you right click your page > click ‘inspect element’ > click ‘console’ tab. Let us know what exactly is the error message because we are unable to replicate the issue. Thank you!

    We updated the tutorial AngularJS v1.6.1. You may want to follow the changes above, it may solve the issues you encounter.

    To answer your question “Is it correct put the modal using jquery?” The MaterializeCSS library we used uses jQuery so there’s really no other way to trigger the modal.

  20. Rogerup
    Rogerup says:

    2 corrections to do:
    – Change, in text, the term “libs” by “assets” which is the used in the code.
    – Code on 7.3 should be var app = angular.module(‘myApp’, [ ]); (That is then replaced in 11.6)

  21. Patrick Were
    Patrick Were says:

    Uncaught Error: [$injector:modulerr] http://errors.angularjs.org/1.6.1/$injector/modulerr?p0=myApp&p1=Error%3A%2…ogleapis.com%2Fajax%2Flibs%2Fangularjs%2F1.6.1%2Fangular.min.js%3A21%3A332)
    at angular.js:38
    at angular.js:4759
    at q (angular.js:357)
    at g (angular.js:4720)
    at eb (angular.js:4642)
    at c (angular.js:1838)
    at Mc (angular.js:1859)
    at pe (angular.js:1744)
    at HTMLDocument. (angular.js:32977)
    at j (jquery.min.js:2)
    (anonymous) @ angular.js:38
    (anonymous) @ angular.js:4759
    q @ angular.js:357
    g @ angular.js:4720
    eb @ angular.js:4642
    c @ angular.js:1838
    Mc @ angular.js:1859
    pe @ angular.js:1744
    (anonymous) @ angular.js:32977
    j @ jquery.min.js:2
    k @ jquery.min.js:2

  22. Donatoh
    Donatoh says:

    Hello sir! You are well hopefully, just say thank you in relation to the help you give us concerning the design of the websites.
    So I would like you to help me because I practice to reproduce your site using your codes but it does not work. This is the second step that does not work. It would be a pleasure to get help from you. Uh !!!!!!!!! Excuse me for my english and thanks in advance

    • Mike Dalisay
      Mike Dalisay says:

      HI @omargrossi:disqus , thank you for following our tutorial. We just updated our tutorial above and now we are not using the dirPagination directive.

      We are currently working on the asynchronous pagination feature and will post the solution soon.

  23. Patryk “Mihawk” Choma
    Patryk “Mihawk” Choma says:

    Hi, I think that on step 7.1 the box containing:
    Read One
    should have the method readOneProduct.
    Great guide anyway, I’m working through it as a “crash course” on SPAs :p the clean code and the comments are great.

Leave a Reply

Want to join the discussion?
Feel free to contribute!

Leave a Reply

This site uses Akismet to reduce spam. Learn how your comment data is processed.