Learn MVC Using Angular xEditable

Introduction

In this article, we will learn MVC using xeditable json data using for html element & tables, which are given below.

  • HTML Control
  • Table

Angular-xeditable:

This is angular directives allows you to create editable element. Such technique is Click to edit or edit to place. It is based on idea of x-editable.

Features

  • It doesn’t depend on any libraries
  • It support bootstrap CSS
  • We can include some extra control from Angular UI Bootstrap
  • It will support must of html5 controls (text, textarea, select, and check box….etc.)

Follow the steps we can use xeditable in Angular JS in MVC.

  • Create MVC project
  • Configure angular xeditable
  • Work with angular xeditable.

Create MVC Project

Open Visual studio 2015

MVC

Go to New menu. Click New & Project. Now, it will open New Project Window.

MVC

You can select ASP.NET Web Application on Framework 4.6. Enter the name of the project in Solution name textbox and click OK button.

MVC

One more Window should appear. Select MVC Template in this popup & click OK button. Now, it starts to play.

Configure Angular xeditable

We will download the xeditable plug in from

Open the _Layout.cshtml and refer the xeditable.js file from the downloaded folder to this view page.

<link href="~/Plugin/angular-xeditable/dist/css/xeditable.css" rel="stylesheet" />
<script src="~/Plugin/angular-xeditable/dist/js/xeditable.js"></script>
My files
<script src="~/App/App.module.js"></script>
<script src="~/App/App.config.js"></script>
<script src="~/App/HtmlctrlController.js"></script>
<script src="~/App/tableController.js"></script>
Angular Module Code

Add dependence “’xeditable’” keyword in angular module after refer the plug in

var XEdit = angular.module('XEdit', ['ui.router','xeditable']);

Angular Controller Code:

Inject the “editableOptions”, “editableThemes” keyword, it will help to improve our UI level

function htmlctrlController($scope, editableOptions, editableThemes, $filter, $http)Set theme in this application, like given below code

editableOptions.theme = 'bs3';
    editableThemes.bs3.inputClass = 'input-sm';
    editableThemes.bs3.buttonsClass = 'btn-sm';
    editableThemes.bs3.submitTpl = '<button type="submit" class="btn btn-success"><span class="fa fa-check"></span></button>';
    editableThemes.bs3.cancelTpl = '<button type="button" class="btn btn-default" ng-click="$form.$cancel()">' +
                                     '<span class="fa fa-times text-muted"></span>' +
                                   '</button>';

Work with Angular xeditable

HTML control

Open HTML page, make it design, using Editable attribute and bind the even null values also.

<a href="" editable-email="xform.htmlctrl.email">{{ xform.htmlctrl.email || &apos;empty&apos; }}</a>

Here, we can see some HTML basic control.

HTML code

  <a href="" editable-tel="xform.htmlctrl.tel" e-pattern="\d{3}-\d{2}-\d{2}" e-title="xxx-xx-xx">{{ xform.htmlctrl.tel || &apos;empty&apos; }}</a>
 <a href="" editable-number="xform.htmlctrl.number" e-min="18">{{ xform.htmlctrl.number || &apos;empty&apos; }}</a>
  <a href="" editable-color="xform.htmlctrl.color">{{ xform.htmlctrl.color || &apos;empty&apos; }}</a>

    <a href="" editable-date="xform.htmlctrl.date">{{ xform.htmlctrl.date || &apos;empty&apos; }}</a>
     <a href="" editable-text="xform.htmlctrl.name">{{ xform.htmlctrl.name || &apos;empty&apos; }}</a>
      <a href="" editable-textarea="xform.htmlctrl.desc" e-rows="3" e-cols="30">{{ xform.htmlctrl.desc || 'no description' }}    </a>
  <a href="" editable-select="xform.htmlctrl3.text" ng-init="xform.loadGroups()" e-ng-options="g.text as g.text for g in xform.groups">{{ xform.htmlctrl3.text || &apos;not set&apos; }}  </a>
<a href="" editable-textarea="xform.htmlctrl.desc" e-rows="3" e-cols="30">{{ xform.htmlctrl.desc || 'no description' }}    </a>

 

Writing Angular control & assign some values for the model. Usually, we have use the ng-Model keyword for data binding but in this case, we want to use editable+ControlName.

Editable keyword Angular/HTML keyword Descriptions
Editable-controlname Ng-Model Binding the data
e-ng-options Ng-options Binding the value as list
e-pattern Ng-pattern Using Validation
e-title Title Set as placeholder
e-min Min Set minimum values

JS code

vm.htmlctrl = {
        email: 'email@example.com',
        tel: '123-45-67',
        number: 29,
        range: 10,
        url: 'http://example.com',
        search: 'blabla',
        date:new Date(),
        color: '#6a4415',
        desc: 'Click and edit the details. '
    };

    vm.htmlctrl2 = {
        status: 2
    };

    vm.statuses = [
      { value: 1, text: 'status1' },
      { value: 2, text: 'status2' },
      { value: 3, text: 'status3' },
      { value: 4, text: 'status4' }
    ];

    vm.showStatus = function () {
        var selected = $filter('filter')(vm.statuses, { value: vm.htmlctrl2.status });
        return (vm.htmlctrl.status && selected.length) ? selected[0].text : 'Not set';
    };

    // select remote
    // ----------------------------------- 

    vm.htmlctrl3 = {
        id: 4,
        text: 'admin' 
    };

    vm.groups = [];

    vm.loadGroups = function () {
        return vm.groups.length ? null : $http.get('server/xeditable-groups.json').success(function (data) {
            vm.groups = data;
        });
    };

    $scope.$watch('htmlctrl3.id', function (newVal, oldVal) {
        if (newVal !== oldVal) {
            var selected = $filter('filter')(vm.groups, { id: vm.htmlctrl3.id });
            vm.htmlctrl3.text = selected.length ? selected[0].text : null;
        }
    });

I have used as a JSON data for editable-Select & the files are given below.

[{
  "id": 1,
  "text": "user"
}, {
  "id": 2,
  "text": "customer"
}, {
  "id": 3,
  "text": "vip"
}, {
  "id": 4,
  "text": "admin"
}] 

Proceed, as shown below.

<a href="" editable-select="xform.htmlctrl3.text" 
ng-init="xform.loadGroups()" 
e-ng-options="g.text as g.text for g in xform.groups">
{{ xform.htmlctrl3.text || &apos;not set&apos; }}  
</a>"

Run the Application. In the output 1, we have archived the binding data to HTML & proceed.

Output 1

MVC

If you have any doubt for on configuration, refer to the links

Table

We can you use xeditable and proceed

Editable Row

This option is mostly useful for all of us, since end users find it easy to interact this way.

HTML code

<table class="table table-bordered table-hover bg-white">
                   <tr style="font-weight: bold">
                       <td style="width:35%">Name</td>
                       <td style="width:20%">Status</td>
                       <td style="width:20%">Group</td>
                       <td style="width:25%">Edit</td>
                   </tr>
                   <tr ng-repeat="user in xtable.users">
                       <td>
                           <!-- editable username (text with validation)-->
                           <span editable-text="user.name" e-name="name" e-form="rowform" onbeforesave="xtable.checkName($data, user.id)" e-required="">{{ user.name || &apos;empty&apos; }}</span>
                       </td>
                       <td>
                           <!-- editable status (select-local)-->
                           <span editable-select="user.status" e-name="status" e-form="rowform" e-ng-options="s.value as s.text for s in xtable.statuses">{{ xtable.showStatus(user) }}</span>
                       </td>
                       <td>
                           <!-- editable group (select-remote)-->
                           <span editable-select="user.group" e-name="group" onshow="xtable.loadGroups()" e-form="rowform" e-ng-options="g.id as g.text for g in xtable.groups">{{ xtable.showGroup(user) }}</span>
                       </td>
                       <td style="white-space: nowrap">
                           <!-- form-->
                           <form editable-form="" name="rowform" onbeforesave="xtable.saveUser($data, user.id)" ng-show="rowform.$visible" shown="xtable.inserted == user" class="form-buttons form-inline">
                               <button type="submit" ng-disabled="rowform.$waiting" title="Save" class="btn btn-sm btn-info">
                                   Save
                               </button>
                               <button type="button" ng-disabled="rowform.$waiting" ng-click="rowform.$cancel()" title="Cancel" class="btn btn-sm btn-default">
                                   Cancel
                               </button>
                           </form>
                           <div ng-show="!rowform.$visible" class="buttons">
                               <button ng-click="rowform.$show()" title="Edit" class="btn btn-sm btn-info">
                                   Edit
                               </button>
                               <button ng-click="xtable.removeUser($index)" title="Delete" class="btn btn-sm btn-danger">
                                   Delete
                               </button>
                           </div>
                       </td>
                   </tr>
               </table>
               <button ng-click="xtable.addUser()" class="btn btn-default">Add row</button>

Angular Controller code

vm.users = [
      { id: 1, name: ' user1', status: 2, group: 4, groupName: 'admin' },
      { id: 2, name: ' user2', status: undefined, group: 3, groupName: 'vip' },
      { id: 3, name: ' user3', status: 2, group: null }
    ];

    vm.statuses = [
      { value: 1, text: 'status1' },
      { value: 2, text: 'status2' },
      { value: 3, text: 'status3' },
      { value: 4, text: 'status4' }
    ];

    vm.groups = [];
    vm.loadGroups = function () {
        return vm.groups.length ? null : $http.get('server/xeditable-groups.json').success(function (data) {
            vm.groups = data;
        });
    };

    vm.showGroup = function (user) {
        if (user.group && vm.groups.length) {
            var selected = $filter('filter')(vm.groups, { id: user.group });
            return selected.length ? selected[0].text : 'Not set';
        } else {
            return user.groupName || 'Not set';
        }
    };

    vm.showStatus = function (user) {
        var selected = [];
        if (user.status) {
            selected = $filter('filter')(vm.statuses, { value: user.status });
        }
        return selected.length ? selected[0].text : 'Not set';
    };

    vm.checkName = function (data, id) {
        if (id === 2 && data !== 'awesome') {
            return 'Username 2 should be `awesome`';
        }
    };

Delete row in the table

vm.removeUser = function (index) {

        vm.users.splice(index, 1);
    };

Add the new row

vm.addUser = function () {
        vm.inserted = {
            id: vm.users.length + 1,
            name: '',
            status: null,
            group: null,
            isNew: true
        };
        vm.users.push(vm.inserted);
    };

Run the Application. If you click Add row button, it will add one new row in this table. Suppose, we can edit or delete in same way. Save button enables, when you are going to edit a row.

Output 2

MVC

Editable Column

We can edit the instance of table column on time.

HTML code

<table class="table table-bordered table-hover bg-white">
                    <tr style="font-weight: bold; white-space: nowrap">
                        <!-- username header-->
                        <td style="width:40%">
                            Name
                            <form editable-form="" name="nameform" onaftersave="xtable.saveColumn('name')" ng-show="nameform.$visible">
                                <button type="submit" ng-disabled="nameform.$waiting" class="btn btn-info">save</button>
                                <button type="button" ng-disabled="nameform.$waiting" ng-click="nameform.$cancel()" class="btn btn-default">cancel</button>
                            </form>
                            <button ng-show="!nameform.$visible" ng-click="nameform.$show()" class="btn  btn-info">
                               Edit
                            </button>
                        </td>
                        <!-- status header-->
                        <td style="width:30%">
                            Status
                            <form editable-form="" name="statusform" onaftersave="xtable.saveColumn('status')" ng-show="statusform.$visible">
                                <button type="submit" ng-disabled="statusform.$waiting" class="btn btn-info">save</button>
                                <button type="button" ng-disabled="statusform.$waiting" ng-click="statusform.$cancel()" class="btn btn-default">cancel</button>
                            </form>
                            <button ng-show="!statusform.$visible" ng-click="statusform.$show()" class="btn  btn-info">
                                Edit
                            </button>
                        </td>
                        <!-- group header-->
                        <td style="width:30%">
                            Group
                            <form editable-form="" name="groupform" onaftersave="xtable.saveColumn('group')" ng-show="groupform.$visible">
                                <button type="submit" ng-disabled="groupform.$waiting" class="btn btn-info">save</button>
                                <button type="button" ng-disabled="groupform.$waiting" ng-click="groupform.$cancel()" class="btn btn-default">cancel</button>
                            </form>
                            <button ng-show="!groupform.$visible" ng-click="groupform.$show()" class="btn btn-info">
                                Edit
                            </button>
                        </td>
                    </tr>
                    <tr ng-repeat="user in xtable.users">
                        <td>
                         
                            <span editable-text="user.name" e-name="name" e-form="nameform" onbeforesave="xtable.checkName($data)">{{ user.name || &apos;empty&apos; }}</span>
                        </td>
                        <td>
                            <span editable-select="user.status" e-name="status" e-form="statusform" e-ng-options="s.value as s.text for s in xtable.statuses">{{ xtable.showStatus(user) }}</span>
                        </td>
                        <td>
                            <span editable-select="user.group" e-name="group" onshow="xtable.loadGroups()" e-form="groupform" e-ng-options="g.id as g.text for g in xtable.groups">{{ xtable.showGroup(user) }}</span>
                        </td>
                    </tr>
                </table>

Once you click Edit button given above the table column header, it will enable to edit mode.

Angular Controller code

vm.saveColumn = function (column) {
        var results = [];
        angular.forEach(vm.users, function (user) {
            alert('Saving column: ' + column);
        });
        return $q.all(results);
    };

 

Output 3

MVC

Editable Table

The whole table into <from > tag with editable-from attribute. It allows to retrieve all the changes.

HTML code

<form editable-form="" name="tableform" onaftersave="xtable.saveTable()" oncancel="xtable.cancel()">
                    <!-- table-->
                    <table class="table table-bordered table-hover bg-white">
                        <tr style="font-weight: bold">
                            <td style="width:40%">Name</td>
                            <td style="width:30%">Status</td>
                            <td style="width:30%">Group</td>
                            <td style="width:30%">
                                <span ng-show="tableform.$visible">Action</span>
                            </td>
                        </tr>
                        <tr ng-repeat="user in xtable.users | filter:filterUser">
                            <td>
                                <!-- editable username (text with validation)-->
                                <span editable-text="user.name" e-form="tableform" onbeforesave="xtable.checkName($data, user.id)">{{ user.name || &apos;empty&apos; }}</span>
                            </td>
                            <td>
                                <!-- editable status (select-local)-->
                                <span editable-select="user.status" e-form="tableform" e-ng-options="s.value as s.text for s in xtable.statuses">{{ xtable.showStatus(user) }}</span>
                            </td>
                            <td>
                                <!-- editable group (select-remote)-->
                                <span editable-select="user.group" e-form="tableform" onshow="xtable.loadGroups()" e-ng-options="g.id as g.text for g in xtable.groups">{{ xtable.showGroup(user) }}</span>
                            </td>
                            <td>
                                <button type="button" ng-show="tableform.$visible" ng-click="deleteUser(user.id)" class="btn btn-danger pull-right">
                                    Delete
                                </button>
                            </td>
                        </tr>
                    </table>
                    <!-- buttons-->
                    <div class="btn-edit">
                        <button type="button" ng-show="!tableform.$visible" ng-click="tableform.$show()" class="btn btn-default">edit</button>
                    </div>
                    <div ng-show="tableform.$visible" class="btn-form">
                        <button type="button" ng-disabled="tableform.$waiting" ng-click="addUser()" class="btn btn-default pull-right">add row</button>
                        <button type="submit" ng-disabled="tableform.$waiting" class="btn btn-info">save</button>
                        <button type="button" ng-disabled="tableform.$waiting" ng-click="tableform.$cancel()" class="btn btn-default">cancel</button>
                    </div>
                </form>

Angular Controller code

vm.filterUser = function (user) {
        return user.isDeleted !== true;
    };
    vm.deleteUser = function (id) {
        var filtered = $filter('filter')(vm.users, { id: id });
        if (filtered.length) {
            filtered[0].isDeleted = true;
        }
    };
    vm.cancel = function () {
        for (var i = vm.users.length; i--;) {
            var user = vm.users[i];
            if (user.isDeleted) {
                delete user.isDeleted;
            }
            if (user.isNew) {
                vm.users.splice(i, 1);
            }
        }
    };
    vm.saveTable = function () {
        var results = [];
        for (var i = vm.users.length; i--;) {
            var user = vm.users[i];
            if (user.isDeleted) {
                vm.users.splice(i, 1);
            }
            if (user.isNew) {
                user.isNew = false;
            }
            alert('Saving Table...');
        }
        return $q.all(results);
    };

Run the Application

Output 4

Before editable table

MVC

After editable table

MVC

Note

New row data will be added in JSON format. Afterwards, click Save button. If we need, we can valid the right data. Don’t forget to add the “editable” keyword, using Angular xeditable.

For source download, click here.

Conclusion

In this article, we have learned MVC, using Angular xeditable. If you have any queries, please tell me through the comments section. Your comments are very valuable.