Codeigniter and Angularjs Crud

  • Posted by Sharad Jaiswal

    Creating Codeigniter and Angularjs Crud in 5 simple steps

    Finding difficulty in creating a CRUD in Codeigniter? CRUD is an abbreviation for Create, Read, Update and Delete. If you are working on Codeigniter project, then this step-by-step process will help you to create a simple and easy CRUD with the help of Angular Js and Codeigniter. Some of the steps in the process are added for a Codeigniter framework i.e. create, delete, edit, list, search & pagination application.

    Here are the product modules that will be done using Angular Js and Codeigniter 3:

    Step1: Create a table for products The very first is to configure the Codeigniter 3 project. In order to configure, go to application/cofig/database.php. Once your file is open, enter the name of database followed by username and password. Create the table for products by using the SQL query:

    CREATE TABLE IF NOT EXISTS `products` (
    `id` int(10) unsigned NOT NULL AUTO_INCREMENT,
    `name` varchar(255) COLLATE utf8_unicode_ci NOT NULL,
    `description` text COLLATE utf8_unicode_ci NOT NULL,
    `created_at` timestamp NULL DEFAULT NULL,
    `updated_at` timestamp NULL DEFAULT NULL,
    PRIMARY KEY (`id`)
    ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=1;
    

    Step 2: Add the route files The second step is to add a route to the route file. Begin by creating templates route, which will get you the html template for the application. Create further routes for product modules such as lists, update, edit and delete. Now insert the code given below in your route file.

    application/config/routes.php

    defined('BASEPATH') OR exit('No direct script access allowed');
    $route['default_controller'] = 'home';
    $route['404_override'] = '';
    $route['translate_uri_dashes'] = FALSE;
    $route['templates/(:any)'] = "templates/view/$1";
    $route['products'] = "products/index";
    $route['productsCreate']['post'] = "products/store";
    $route['productsEdit/(:any)'] = "products/edit/$1";
    $route['productsUpdate/(:any)']['put'] = "products/update/$1";
    $route['productsDelete/(:any)']['delete'] = "products/delete/$1";
    

    Note: Above are sample routes you can make your own routes in Codeigniter. Step 3: Create the controller The very first step is to create two separate controllers where one would be for template route and other would be for product route. Begin by creating a template controller in application/controllers/Templates.php path and insert the code given below:

    application/controllers/Templates.php

    defined('BASEPATH') OR exit('No direct script access allowed');
    class Templates extends CI_Controller {
    public function view($view)
    {
    $this->load->view('templates/'.$view);
    }
    }
    

    Now create the next controller where you can add function for the following: update, list, create, delete and edit. You can develop the product.php file in application/controllers/Products.php path and insert the code given below:

    application/controllers/Products.php

    defined('BASEPATH') OR exit('No direct script access allowed');
    class Products extends CI_Controller {
    public function index()
    {
    $this->load->database();
    if(!empty($this->input->get("search"))){
    $this->db->like('title', $this->input->get("search"));
    $this->db->or_like('description', $this->input->get("search"));
    }
    $this->db->limit(5, ($this->input->get("page",1) - 1) * 5);
    $query = $this->db->get("products");
    $data['data'] = $query->result();
    $data['total'] = $this->db->count_all("products");
    echo json_encode($data);
    }
    public function store()
    {
    $this->load->database();
    $_POST = json_decode(file_get_contents('php://input'), true);
    $insert = $this->input->post();
    $this->db->insert('products', $insert);
    $id = $this->db->insert_id();
    $q = $this->db->get_where('products', array('id' => $id));
    echo json_encode($q->row());
    }
    public function edit($id)
    {
    $this->load->database();
    $q = $this->db->get_where('products', array('id' => $id));
    echo json_encode($q->row());
    }
    public function update($id)
    {
    $this->load->database();
    $_POST = json_decode(file_get_contents('php://input'), true);
    $insert = $this->input->post();
    $this->db->where('id', $id);
    $this->db->update('products', $insert);
    $q = $this->db->get_where('products', array('id' => $id));
    echo json_encode($q->row());
    }
    public function delete($id)
    {
    $this->load->database();
    $this->db->where('id', $id);
    $this->db->delete('products');
    echo json_encode(['success'=>true]);
    }
    }
    

    Step 4: Integrating  Angular Js with Codeigniter This step will help you manage both controller and Angular Js route. In order to do that, go to the main folder and create an app directory and route.js file. Now insert the following code given below: app/route.js

    var app = angular.module('myApp',['ngRoute','angularUtils.directives.dirPagination']);
    app.config(['$routeProvider',
    function($routeProvider) {
    $routeProvider.
    when('/', {
    templateUrl: 'templates/home.html',
    controller: 'AdminController'
    }).
    when('/products', {
    templateUrl: 'templates/products.html',
    controller: 'ProductController'
    });
    }]);
    

    The next step is to create a folder within the app folder for controllers. The folder will be 'ProductController.js' file app/controllers/ProductController.js

    app.controller('ProductController', function(dataFactory,$scope,$http){
    $scope.data = [];
    $scope.pageNumber = 1;
    $scope.libraryTemp = {};
    $scope.totalProductTemp = {};
    $scope.totalProducts = 0;
    $scope.pageChanged = function(newPage) {
    getResultsPage(newPage);
    };
    getResultsPage(1);
    function getResultsPage(pageNumber) {
    if(! $.isEmptyObject($scope.libraryTemp)){
    dataFactory.httpRequest('/products?search='+$scope.searchText+'&page='+pageNumber).then(function(data) {
    $scope.data = data.data;
    $scope.totalProducts = data.total;
    $scope.pageNumber = pageNumber;
    });
    }else{
    dataFactory.httpRequest('/products?page='+pageNumber).then(function(data) {
    $scope.data = data.data;
    $scope.totalProducts = data.total;
    $scope.pageNumber = pageNumber;
    });
    }
    }
    $scope.searchDB = function(){
    if($scope.searchText.length >= 3){
    if($.isEmptyObject($scope.libraryTemp)){
    $scope.libraryTemp = $scope.data;
    $scope.totalProductsTemp = $scope.totalProducts;
    $scope.data = {};
    }
    getResultsPage(1);
    }else{
    if(! $.isEmptyObject($scope.libraryTemp)){
    $scope.data = $scope.libraryTemp ;
    $scope.totalProducts = $scope.totalProductsTemp;
    $scope.libraryTemp = {};
    }
    }
    }
    $scope.saveAdd = function(){
    dataFactory.httpRequest('productsCreate','POST',{},$scope.form).then(function(data) {
    $scope.data.push(data);
    $(".modal").modal("hide");
    });
    }
    $scope.edit = function(id){
    dataFactory.httpRequest('productsEdit/'+id).then(function(data) {
    console.log(data);
    $scope.form = data;
    });
    }
    $scope.saveEdit = function(){
    dataFactory.httpRequest('productsUpdate/'+$scope.form.id,'PUT',{},$scope.form).then(function(data) {
    $(".modal").modal("hide");
    $scope.data = modifyTableAPI($scope.data,data.id,data);
    });
    }
    $scope.remove = function(product,index){
    var result = confirm("Are you sure delete this product?");
    if (result) {
    dataFactory.httpRequest('productsDelete/'+product.id,'DELETE').then(function(data) {
    $scope.data.splice(index,1);
    });
    }
    }
    });
    

    Now go to the app directory and create a folder called helper and create a file named 'myHelper.js'  (app/helper/myHelper.js) which will be responsible for the helper function. app/helper/myHelper.js

    function modifyTableAPI(originalData,id,response){
    angular.forEach(originalData, function (product,key) {
    if(product.id == id){
    originalData[key] = response;
    }
    });
    return originalData;
    }
    

    Create a new folder named 'packages' and a file dirPagination.js (app/packages/dirPagination.js). Now insert the following code given below:

    dirPagination.js

    /**
    * dirPagination - AngularJS module for paginating (almost) anything.
    *
    *
    * Credits
    * =======
    *
    * Daniel Tabuenca: https://groups.google.com/d/msg/angular/an9QpzqIYiM/r8v-3W1X5vcJ
    * for the idea on how to dynamically invoke the ng-repeat directive.
    *
    * I borrowed a couple of lines and a few attribute names from the AngularUI Bootstrap project:
    * https://github.com/angular-ui/bootstrap/blob/master/src/pagination/pagination.js
    *
    * Copyright 2014 Michael Bromley <michael@michaelbromley.co.uk>
    */
    
    (function() {
    
    /**
    * Config
    */
    var moduleName = 'angularUtils.directives.dirPagination';
    var DEFAULT_ID = '__default';
    
    /**
    * Module
    */
    angular.module(moduleName, [])
    .directive('dirPaginate', ['$compile', '$parse', 'paginationService', dirPaginateDirective])
    .directive('dirPaginateNoCompile', noCompileDirective)
    .directive('dirPaginationControls', ['paginationService', 'paginationTemplate', dirPaginationControlsDirective])
    .filter('productsPerPage', ['paginationService', productsPerPageFilter])
    .service('paginationService', paginationService)
    .provider('paginationTemplate', paginationTemplateProvider)
    .run(['$templateCache',dirPaginationControlsTemplateInstaller]);
    
    function dirPaginateDirective($compile, $parse, paginationService) {
    
    return {
    terminal: true,
    multiElement: true,
    priority: 100,
    compile: dirPaginationCompileFn
    };
    
    function dirPaginationCompileFn(tElement, tAttrs){
    
    var expression = tAttrs.dirPaginate;
    // regex taken directly from https://github.com/angular/angular.js/blob/v1.4.x/src/ng/directive/ngRepeat.js#L339
    var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+as\s+([\s\S]+?))?(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
    
    var filterPattern = /\|\s*productsPerPage\s*:\s*(.*\(\s*\w*\)|([^\)]*?(?=\s+as\s+))|[^\)]*)/;
    if (match[2].match(filterPattern) === null) {
    throw 'pagination directive: the \'productsPerPage\' filter must be set.';
    }
    var productsPerPageFilterRemoved = match[2].replace(filterPattern, '');
    var collectionGetter = $parse(productsPerPageFilterRemoved);
    
    addNoCompileAttributes(tElement);
    
    // If any value is specified for paginationId, we register the un-evaluated expression at this stage for the benefit of any
    // dir-pagination-controls directives that may be looking for this ID.
    var rawId = tAttrs.paginationId || DEFAULT_ID;
    paginationService.registerInstance(rawId);
    
    return function dirPaginationLinkFn(scope, element, attrs){
    
    // Now that we have access to the `scope` we can interpolate any expression given in the paginationId attribute and
    // potentially register a new ID if it evaluates to a different value than the rawId.
    var paginationId = $parse(attrs.paginationId)(scope) || attrs.paginationId || DEFAULT_ID;
    paginationService.registerInstance(paginationId);
    
    var repeatExpression = getRepeatExpression(expression, paginationId);
    addNgRepeatToElement(element, attrs, repeatExpression);
    
    removeTemporaryAttributes(element);
    var compiled = $compile(element);
    
    var currentPageGetter = makeCurrentPageGetterFn(scope, attrs, paginationId);
    paginationService.setCurrentPageParser(paginationId, currentPageGetter, scope);
    
    if (typeof attrs.totalProducts !== 'undefined') {
    paginationService.setAsyncModeTrue(paginationId);
    scope.$watch(function() {
    return $parse(attrs.totalProducts)(scope);
    }, function (result) {
    if (0 <= result) {
    paginationService.setCollectionLength(paginationId, result);
    }
    });
    } else {
    scope.$watchCollection(function() {
    return collectionGetter(scope);
    }, function(collection) {
    if (collection) {
    var collectionLength = (collection instanceof Array) ? collection.length : Object.keys(collection).length;
    paginationService.setCollectionLength(paginationId, collectionLength);
    }
    });
    }
    
    // Delegate to the link function returned by the new compilation of the ng-repeat
    compiled(scope);
    };
    }
    
    /**
    * If a pagination id has been specified, we need to check that it is present as the second argument passed to
    * the productsPerPage filter. If it is not there, we add it and return the modified expression.
    *
    * @param expression
    * @param paginationId
    * @returns {*}
    */
    function getRepeatExpression(expression, paginationId) {
    var repeatExpression,
    idDefinedInFilter = !!expression.match(/(\|\s*productsPerPage\s*:[^|]*:[^|]*)/);
    
    if (paginationId !== DEFAULT_ID && !idDefinedInFilter) {
    repeatExpression = expression.replace(/(\|\s*productsPerPage\s*:\s*[^|\s]*)/, "$1 : '" + paginationId + "'");
    } else {
    repeatExpression = expression;
    }
    
    return repeatExpression;
    }
    
    /**
    * Adds the ng-repeat directive to the element. In the case of multi-element (-start, -end) it adds the
    * appropriate multi-element ng-repeat to the first and last element in the range.
    * @param element
    * @param attrs
    * @param repeatExpression
    */
    function addNgRepeatToElement(element, attrs, repeatExpression) {
    if (element[0].hasAttribute('dir-paginate-start') || element[0].hasAttribute('data-dir-paginate-start')) {
    // using multiElement mode (dir-paginate-start, dir-paginate-end)
    attrs.$set('ngRepeatStart', repeatExpression);
    element.eq(element.length - 1).attr('ng-repeat-end', true);
    } else {
    attrs.$set('ngRepeat', repeatExpression);
    }
    }
    
    /**
    * Adds the dir-paginate-no-compile directive to each element in the tElement range.
    * @param tElement
    */
    function addNoCompileAttributes(tElement) {
    angular.forEach(tElement, function(el) {
    if (el.nodeType === 1) {
    angular.element(el).attr('dir-paginate-no-compile', true);
    }
    });
    }
    
    /**
    * Removes the variations on dir-paginate (data-, -start, -end) and the dir-paginate-no-compile directives.
    * @param element
    */
    function removeTemporaryAttributes(element) {
    angular.forEach(element, function(el) {
    if (el.nodeType === 1) {
    angular.element(el).removeAttr('dir-paginate-no-compile');
    }
    });
    element.eq(0).removeAttr('dir-paginate-start').removeAttr('dir-paginate').removeAttr('data-dir-paginate-start').removeAttr('data-dir-paginate');
    element.eq(element.length - 1).removeAttr('dir-paginate-end').removeAttr('data-dir-paginate-end');
    }
    
    /**
    * Creates a getter function for the current-page attribute, using the expression provided or a default value if
    * no current-page expression was specified.
    *
    * @param scope
    * @param attrs
    * @param paginationId
    * @returns {*}
    */
    function makeCurrentPageGetterFn(scope, attrs, paginationId) {
    var currentPageGetter;
    if (attrs.currentPage) {
    currentPageGetter = $parse(attrs.currentPage);
    } else {
    // If the current-page attribute was not set, we'll make our own.
    // Replace any non-alphanumeric characters which might confuse
    // the $parse service and give unexpected results.
    // See https://github.com/michaelbromley/angularUtils/issues/233
    var defaultCurrentPage = (paginationId + '__currentPage').replace(/\W/g, '_');
    scope[defaultCurrentPage] = 1;
    currentPageGetter = $parse(defaultCurrentPage);
    }
    return currentPageGetter;
    }
    }
    
    /**
    * This is a helper directive that allows correct compilation when in multi-element mode (ie dir-paginate-start, dir-paginate-end).
    * It is dynamically added to all elements in the dir-paginate compile function, and it prevents further compilation of
    * any inner directives. It is then removed in the link function, and all inner directives are then manually compiled.
    */
    function noCompileDirective() {
    return {
    priority: 5000,
    terminal: true
    };
    }
    
    function dirPaginationControlsTemplateInstaller($templateCache) {
    $templateCache.put('angularUtils.directives.dirPagination.template', '<ul class="pagination" ng-if="1 < pages.length || !autoHide"><li ng-if="boundaryLinks" ng-class="{ disabled : pagination.current == 1 }"><a href="ng-click="setCurrent(1)">&laquo;</a></li><li ng-if="directionLinks" ng-class="{ disabled : pagination.current == 1 }"><a href="ng-click="setCurrent(pagination.current - 1)">&lsaquo;</a></li><li ng-repeat="pageNumber in pages track by tracker(pageNumber, $index)" ng-class="{ active : pagination.current == pageNumber, disabled : pageNumber == \'...\' || ( ! autoHide && pages.length === 1 ) }"><a href="ng-click="setCurrent(pageNumber)">{{ pageNumber }}</a></li><li ng-if="directionLinks" ng-class="{ disabled : pagination.current == pagination.last }"><a href="ng-click="setCurrent(pagination.current + 1)">&rsaquo;</a></li><li ng-if="boundaryLinks" ng-class="{ disabled : pagination.current == pagination.last }"><a href="ng-click="setCurrent(pagination.last)">&raquo;</a></li></ul>');
    }
    
    function dirPaginationControlsDirective(paginationService, paginationTemplate) {
    
    var numberRegex = /^\d+$/;
    
    return {
    restrict: 'AE',
    templateUrl: function(elem, attrs) {
    return attrs.templateUrl || paginationTemplate.getPath();
    },
    scope: {
    maxSize: '=?',
    onPageChange: '&?',
    paginationId: '=?',
    autoHide: '=?'
    },
    link: dirPaginationControlsLinkFn
    };
    
    function dirPaginationControlsLinkFn(scope, element, attrs) {
    
    // rawId is the un-interpolated value of the pagination-id attribute. This is only important when the corresponding dir-paginate directive has
    // not yet been linked (e.g. if it is inside an ng-if block), and in that case it prevents this controls directive from assuming that there is
    // no corresponding dir-paginate directive and wrongly throwing an exception.
    var rawId = attrs.paginationId || DEFAULT_ID;
    var paginationId = scope.paginationId || attrs.paginationId || DEFAULT_ID;
    
    if (!paginationService.isRegistered(paginationId) && !paginationService.isRegistered(rawId)) {
    var idMessage = (paginationId !== DEFAULT_ID) ? ' (id: ' + paginationId + ') ' : ' ';
    if (window.console) {
    console.warn('Pagination directive: the pagination controls' + idMessage + 'cannot be used without the corresponding pagination directive, which was not found at link time.');
    }
    }
    
    if (!scope.maxSize) { scope.maxSize = 9; }
    scope.autoHide = scope.autoHide === undefined ? true : scope.autoHide;
    scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : true;
    scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : false;
    
    var paginationRange = Math.max(scope.maxSize, 5);
    scope.pages = [];
    scope.pagination = {
    last: 1,
    current: 1
    };
    scope.range = {
    lower: 1,
    upper: 1,
    total: 1
    };
    
    scope.$watch('maxSize', function(val) {
    if (val) {
    paginationRange = Math.max(scope.maxSize, 5);
    generatePagination();
    }
    });
    
    scope.$watch(function() {
    if (paginationService.isRegistered(paginationId)) {
    return (paginationService.getCollectionLength(paginationId) + 1) * paginationService.getProductsPerPage(paginationId);
    }
    }, function(length) {
    if (0 < length) {
    generatePagination();
    }
    });
    
    scope.$watch(function() {
    if (paginationService.isRegistered(paginationId)) {
    return (paginationService.getProductsPerPage(paginationId));
    }
    }, function(current, previous) {
    if (current != previous && typeof previous !== 'undefined') {
    goToPage(scope.pagination.current);
    }
    });
    
    scope.$watch(function() {
    if (paginationService.isRegistered(paginationId)) {
    return paginationService.getCurrentPage(paginationId);
    }
    }, function(currentPage, previousPage) {
    if (currentPage != previousPage) {
    goToPage(currentPage);
    }
    });
    
    scope.setCurrent = function(num) {
    if (paginationService.isRegistered(paginationId) && isValidPageNumber(num)) {
    num = parseInt(num, 10);
    paginationService.setCurrentPage(paginationId, num);
    }
    };
    
    /**
    * Custom "track by" function which allows for duplicate "..." entries on long lists,
    * yet fixes the problem of wrongly-highlighted links which happens when using
    * "track by $index" - see https://github.com/michaelbromley/angularUtils/issues/153
    * @param id
    * @param index
    * @returns {string}
    */
    scope.tracker = function(id, index) {
    return id + '_' + index;
    };
    
    function goToPage(num) {
    if (paginationService.isRegistered(paginationId) && isValidPageNumber(num)) {
    var oldPageNumber = scope.pagination.current;
    
    scope.pages = generatePagesArray(num, paginationService.getCollectionLength(paginationId), paginationService.getProductsPerPage(paginationId), paginationRange);
    scope.pagination.current = num;
    updateRangeValues();
    
    // if a callback has been set, then call it with the page number as the first argument
    // and the previous page number as a second argument
    if (scope.onPageChange) {
    scope.onPageChange({
    newPageNumber : num,
    oldPageNumber : oldPageNumber
    });
    }
    }
    }
    
    function generatePagination() {
    if (paginationService.isRegistered(paginationId)) {
    var page = parseInt(paginationService.getCurrentPage(paginationId)) || 1;
    scope.pages = generatePagesArray(page, paginationService.getCollectionLength(paginationId), paginationService.getProductsPerPage(paginationId), paginationRange);
    scope.pagination.current = page;
    scope.pagination.last = scope.pages[scope.pages.length - 1];
    if (scope.pagination.last < scope.pagination.current) {
    scope.setCurrent(scope.pagination.last);
    } else {
    updateRangeValues();
    }
    }
    }
    
    /**
    * This function updates the values (lower, upper, total) of the `scope.range` object, which can be used in the pagination
    * template to display the current page range, e.g. "showing 21 - 40 of 144 results";
    */
    function updateRangeValues() {
    if (paginationService.isRegistered(paginationId)) {
    var currentPage = paginationService.getCurrentPage(paginationId),
    productsPerPage = paginationService.getProductsPerPage(paginationId),
    totalProducts = paginationService.getCollectionLength(paginationId);
    
    scope.range.lower = (currentPage - 1) * productsPerPage + 1;
    scope.range.upper = Math.min(currentPage * productsPerPage, totalProducts);
    scope.range.total = totalProducts;
    }
    }
    function isValidPageNumber(num) {
    return (numberRegex.test(num) && (0 < num && num <= scope.pagination.last));
    }
    }
    
    /**
    * Generate an array of page numbers (or the '...' string) which is used in an ng-repeat to generate the
    * links used in pagination
    *
    * @param currentPage
    * @param rowsPerPage
    * @param paginationRange
    * @param collectionLength
    * @returns {Array}
    */
    function generatePagesArray(currentPage, collectionLength, rowsPerPage, paginationRange) {
    var pages = [];
    var totalPages = Math.ceil(collectionLength / rowsPerPage);
    var halfWay = Math.ceil(paginationRange / 2);
    var position;
    
    if (currentPage <= halfWay) {
    position = 'start';
    } else if (totalPages - halfWay < currentPage) {
    position = 'end';
    } else {
    position = 'middle';
    }
    
    var ellipsesNeeded = paginationRange < totalPages;
    var i = 1;
    while (i <= totalPages && i <= paginationRange) {
    var pageNumber = calculatePageNumber(i, currentPage, paginationRange, totalPages);
    
    var openingEllipsesNeeded = (i === 2 && (position === 'middle' || position === 'end'));
    var closingEllipsesNeeded = (i === paginationRange - 1 && (position === 'middle' || position === 'start'));
    if (ellipsesNeeded && (openingEllipsesNeeded || closingEllipsesNeeded)) {
    pages.push('...');
    } else {
    pages.push(pageNumber);
    }
    i ++;
    }
    return pages;
    }
    
    /**
    * Given the position in the sequence of pagination links [i], figure out what page number corresponds to that position.
    *
    * @param i
    * @param currentPage
    * @param paginationRange
    * @param totalPages
    * @returns {*}
    */
    function calculatePageNumber(i, currentPage, paginationRange, totalPages) {
    var halfWay = Math.ceil(paginationRange/2);
    if (i === paginationRange) {
    return totalPages;
    } else if (i === 1) {
    return i;
    } else if (paginationRange < totalPages) {
    if (totalPages - halfWay < currentPage) {
    return totalPages - paginationRange + i;
    } else if (halfWay < currentPage) {
    return currentPage - halfWay + i;
    } else {
    return i;
    }
    } else {
    return i;
    }
    }
    }
    
    /**
    * This filter slices the collection into pages based on the current page number and number of products per page.
    * @param paginationService
    * @returns {Function}
    */
    function productsPerPageFilter(paginationService) {
    
    return function(collection, productsPerPage, paginationId) {
    if (typeof (paginationId) === 'undefined') {
    paginationId = DEFAULT_ID;
    }
    if (!paginationService.isRegistered(paginationId)) {
    throw 'pagination directive: the productsPerPage id argument (id: ' + paginationId + ') does not match a registered pagination-id.';
    }
    var end;
    var start;
    if (angular.isObject(collection)) {
    productsPerPage = parseInt(productsPerPage) || 9999999999;
    if (paginationService.isAsyncMode(paginationId)) {
    start = 0;
    } else {
    start = (paginationService.getCurrentPage(paginationId) - 1) * productsPerPage;
    }
    end = start + productsPerPage;
    paginationService.setProductsPerPage(paginationId, productsPerPage);
    
    if (collection instanceof Array) {
    // the array just needs to be sliced
    return collection.slice(start, end);
    } else {
    // in the case of an object, we need to get an array of keys, slice that, then map back to
    // the original object.
    var slicedObject = {};
    angular.forEach(keys(collection).slice(start, end), function(key) {
    slicedObject[key] = collection[key];
    });
    return slicedObject;
    }
    } else {
    return collection;
    }
    };
    }
    
    /**
    * Shim for the Object.keys() method which does not exist in IE < 9
    * @param obj
    * @returns {Array}
    */
    function keys(obj) {
    if (!Object.keys) {
    var objKeys = [];
    for (var i in obj) {
    if (obj.hasOwnProperty(i)) {
    objKeys.push(i);
    }
    }
    return objKeys;
    } else {
    return Object.keys(obj);
    }
    }
    
    /**
    * This service allows the various parts of the module to communicate and stay in sync.
    */
    function paginationService() {
    
    var instances = {};
    var lastRegisteredInstance;
    
    this.registerInstance = function(instanceId) {
    if (typeof instances[instanceId] === 'undefined') {
    instances[instanceId] = {
    asyncMode: false
    };
    lastRegisteredInstance = instanceId;
    }
    };
    
    this.isRegistered = function(instanceId) {
    return (typeof instances[instanceId] !== 'undefined');
    };
    
    this.getLastInstanceId = function() {
    return lastRegisteredInstance;
    };
    
    this.setCurrentPageParser = function(instanceId, val, scope) {
    instances[instanceId].currentPageParser = val;
    instances[instanceId].context = scope;
    };
    this.setCurrentPage = function(instanceId, val) {
    instances[instanceId].currentPageParser.assign(instances[instanceId].context, val);
    };
    this.getCurrentPage = function(instanceId) {
    var parser = instances[instanceId].currentPageParser;
    return parser ? parser(instances[instanceId].context) : 1;
    };
    
    this.setProductsPerPage = function(instanceId, val) {
    instances[instanceId].productsPerPage = val;
    };
    this.getProductsPerPage = function(instanceId) {
    return instances[instanceId].productsPerPage;
    };
    
    this.setCollectionLength = function(instanceId, val) {
    instances[instanceId].collectionLength = val;
    };
    this.getCollectionLength = function(instanceId) {
    return instances[instanceId].collectionLength;
    };
    
    this.setAsyncModeTrue = function(instanceId) {
    instances[instanceId].asyncMode = true;
    };
    
    this.isAsyncMode = function(instanceId) {
    return instances[instanceId].asyncMode;
    };
    }
    
    /**
    * This provider allows global configuration of the template path used by the dir-pagination-controls directive.
    */
    function paginationTemplateProvider() {
    
    var templatePath = 'angularUtils.directives.dirPagination.template';
    
    this.setPath = function(path) {
    templatePath = path;
    };
    
    this.$get = function() {
    return {
    getPath: function() {
    return templatePath;
    }
    };
    };
    }
    })();
    

    Next, create a new folder called 'services' and a file myServices.js (app/services/myServices.js). app/services/myServices.js

    app.factory('dataFactory', function($http) {
    var myService = {
    httpRequest: function(url,method,params,dataPost,upload) {
    var passParameters = {};
    passParameters.url = url;
    if (typeof method == 'undefined'){
    passParameters.method = 'GET';
    }else{
    passParameters.method = method;
    }
    if (typeof params != 'undefined'){
    passParameters.params = params;
    passParameters.params = params;
    }
    if (typeof dataPost != 'undefined'){
    passParameters.data = dataPost;
    }
    if (typeof upload != 'undefined'){
    passParameters.upload = upload;
    }
    var promise = $http(passParameters).then(function (response) {
    if(typeof response.data == 'string' && response.data != 1){
    if(response.data.substr('loginMark')){
    location.reload();
    return;
    }
    $.gritter.add({
    title: 'Application',
    text: response.data
    });
    return false;
    }
    if(response.data.jsMessage){
    $.gritter.add({
    title: response.data.jsTitle,
    text: response.data.jsMessage
    });
    }
    return response.data;
    },function(){
    $.gritter.add({
    title: 'Application',
    text: 'An error occured while processing your request.'
    });
    });
    return promise;
    }
    };
    return myService;
    });
    

    Step 5: Creating the view This is the final step where create new file welcome_message.php in application/views/ directory and insert the following code in it: application/views/welcome_message.php

    <html lang="en">
    <head>
    <title>Codeigniter 3.X</title>
    <!-- Fonts -->
    <link href='//fonts.googleapis.com/css?family=Roboto:400,300' rel='stylesheet' type='text/css'>
    <link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.0.0/css/bootstrap.min.css">
    <script src="//cdnjs.cloudflare.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
    <script src="//cdnjs.cloudflare.com/ajax/libs/twitter-bootstrap/3.3.1/js/bootstrap.min.js"></script>
    <!-- Angular JS -->
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.2/angular-route.min.js"></script>
    <!-- MY App -->
    <script src="app/packages/dirPagination.js"></script>
    <script src="app/routes.js"></script>
    <script src="app/services/myServices.js"></script>
    <script src="app/helper/myHelper.js"></script>
    <!-- App Controller -->
    <script src="app/controllers/ProductController.js"></script>
    </head>
    <body ng-app="main-App">
    <nav class="navbar navbar-default">
    <div class="container-fluid">
    <div class="navbar-header">
    <button type="button" class="navbar-toggle collapsed" data-toggle="collapse" data-target="#bs-example-navbar-collapse-1">
    <span class="sr-only">Toggle Navigation</span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
    <span class="icon-bar"></span>
    </button>
    <a class="navbar-brand" href="#">Codeigniter 3.x CRUD</a>
    </div>
    <div class="collapse navbar-collapse" id="bs-example-navbar-collapse-1">
    <ul class="nav navbar-nav">
    <li><a href="#/">Home</a></li>
    <li><a href="#/products">Products</a></li>
    </ul>
    </div>
    </div>
    </nav>
    <div class="container">
    <ng-view></ng-view>
    </div>
    </body>
    </html>
    

    Also, create a template folder inside the views folder along with three HTML files. Name them properly and code below them in it. 1. application/views/templates/home.html

    <h2>Welcome to Dashboard</h2>
    

    2. application/views/templates/products.html

    <div class="row">
    <div class="col-lg-12 margin-tb">
    <div class="pull-left">
    <h1>Products CRUD</h1>
    </div>
    <div class="pull-right" style="padding-top:30px">
    <div class="box-tools" style="display:inline-table">
    <div class="input-group">
    <input type="text" class="form-control input-sm ng-valid ng-dirty" placeholder="Search" ng-change="searchDB()" ng-model="searchText" name="table_search" title="" tooltip="" data-original-title="Min character length is 3">
    <span class="input-group-addon">Search</span>
    </div>
    </div>
    <button class="btn btn-success" data-toggle="modal" data-target="#create-user">Create New Product</button>
    </div>
    </div>
    </div>
    <table class="table table-bordered pagin-table">
    <thead>
    <tr>
    <th>No</th>
    <th>Name</th>
    <th>Description</th>
    <th width="330px">Action</th>
    </tr>
    </thead>
    <tbody>
    <tr dir-paginate="value in data | productsPerPage:5" total-products="totalProducts">
    <td>{{ $index + 1 }}</td>
    <td>{{ value.name }}</td>
    <td>{{ value.description }}</td>
    <td>
    <button data-toggle="modal" ng-click="edit(value.id)" data-target="#edit-data" class="btn btn-primary">Edit</button>
    <button ng-click="remove(value,$index)" class="btn btn-danger">Delete</button>
    </td>
    </tr>
    </tbody>
    </table>
    <dir-pagination-controls class="pull-right" on-page-change="pageChanged(newPageNumber)" template-url="templates/dirPagination.html" ></dir-pagination-controls>
    <!-- Create Modal -->
    <div class="modal fade" id="create-user" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    <div class="modal-dialog" role="document">
    <div class="modal-content">
    <form method="POST" name="addProduct" role="form" ng-submit="saveAdd()">
    <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
    <h4 class="modal-title" id="myModalLabel">Create Product</h4>
    </div>
    <div class="modal-body">
    <div class="container">
    <div class="row">
    <div class="col-xs-12 col-sm-6 col-md-6">
    <strong>Title : </strong>
    <div class="form-group">
    <input ng-model="form.title" type="text" placeholder="Name" name="title" class="form-control" required />
    </div>
    </div>
    <div class="col-xs-12 col-sm-6 col-md-6">
    <strong>Description : </strong>
    <div class="form-group" >
    <textarea ng-model="form.description" class="form-control" required>
    </textarea>
    </div>
    </div>
    </div>
    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
    <button type="submit" ng-disabled="addProduct.$invalid" class="btn btn-primary">Submit</button>
    </div>
    </div>
    </form>
    </div>
    </div>
    </div>
    </div>
    <!-- Edit Modal -->
    <div class="modal fade" id="edit-data" tabindex="-1" role="dialog" aria-labelledby="myModalLabel">
    <div class="modal-dialog" role="document">
    <div class="modal-content">
    <form method="POST" name="editProduct" role="form" ng-submit="saveEdit()">
    <input ng-model="form.id" type="hidden" placeholder="Name" name="name" class="form-control" />
    <div class="modal-header">
    <button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
    <h4 class="modal-title" id="myModalLabel">Edit Product</h4>
    </div>
    <div class="modal-body">
    <div class="container">
    <div class="row">
    <div class="col-xs-12 col-sm-6 col-md-6">
    <div class="form-group">
    <input ng-model="form.title" type="text" placeholder="Name" name="title" class="form-control" required />
    </div>
    </div>
    <div class="col-xs-12 col-sm-6 col-md-6">
    <div class="form-group">
    <textarea ng-model="form.description" class="form-control" required>
    </textarea>
    </div>
    </div>
    </div>
    <button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
    <button type="submit" ng-disabled="editProduct.$invalid" class="btn btn-primary create-crud">Submit</button>
    </div>
    </div>
    </form>
    </div>
    </div>
    </div>
    </div>
    

    3. application/views/templates/dirPagination.html

    <ul class="pagination pull-right" ng-if="1 < pages.length">
    <li ng-if="boundaryLinks" ng-class="{ disabled : pagination.current == 1 }">
    <a href="ng-click="setCurrent(1)">«</a>
    </li>
    <li ng-if="directionLinks" ng-class="{ disabled : pagination.current == 1 }">
    <a href="ng-click="setCurrent(pagination.current - 1)">‹</a>
    </li>
    <li ng-repeat="pageNumber in pages track by $index" ng-class="{ active : pagination.current == pageNumber, disabled : pageNumber == '...' }">
    <a href="ng-click="setCurrent(pageNumber)">{{ pageNumber }}</a>
    </li>
    <li ng-if="directionLinks" ng-class="{ disabled : pagination.current == pagination.last }">
    <a href="ng-click="setCurrent(pagination.current + 1)">›</a>
    </li>
    <li ng-if="boundaryLinks" ng-class="{ disabled : pagination.current == pagination.last }">
    <a href="ng-click="setCurrent(pagination.last)">»</a>
    </li>
    </ul>
    

    Thus, this step by step process will help you run an application with Crud, search and Pagination using Angular Js and Codeigniter.

Please Login or Register to leave a response.

Related Articles

PHP Tutorials

Top 6 Open Source PHP CMS (content management system)

CMS: Content Management System allows publishing, editing, modifying and maintaining content via a central interface. CMS is used to avoid complete coding for building the site from scratch. Some pre...

PHP Tutorials

5 Best E-commerce Platforms for PHP

PHP has a lot of features and benefits for the developers that help them design or develop more and more options and features for the consumers. E-commerce, as we all know, is exponentially growing wi..

PHP Tutorials

Installing Apache PHP MySQL on Ubuntu 18.04

Installing Apache PHP MySQL on Ubuntu 18.04:In this article, we are going to see how to create a LAMP stack environment on Ubuntu 18.04. Note: In order to run commands to install Lamp stack you need r..