2015年12月30日 星期三

[AngularJS] Disable Link with ngClass

 AngularJS  


Introduction


We cannot directly disable a link (< a href >) by ngDisabled.
However, we can change the CSS by ngClass to disable it.


Environment

l   AngularJS v1.4.8


▌Sample



CSS


.linkdisabled {
  color: darkgrey;
  cursor: default;
  pointer-events: none;
}



HTML

<div ng-app="app" ng-controller="MyCtrl">
  <a href="#" ng-class='LinkStyle'>My Link</a>
  <br><br>
  <input type="button" value="Enable Link" ng-click="EnableLink()" />
  <input type="button" value="Disable Link" ng-click="DisableLink()" />
</div>



JS

var app = angular.module('app', [])
  .controller('MyCtrl', function($scope) {

    $scope.EnableLink = function() {
      $scope.LinkStyle = "";
    }
    $scope.DisableLink = function() {
      $scope.LinkStyle = "linkdisabled";
    }

  });






Reference



2015年12月21日 星期一

[AngularJS] Async design with $q deferred and promise

 AngularJS  


Introduction


The explanation on $q in AngularJS Document :

A service that helps you run functions asynchronously, and use their return values (or exceptions) when they are done processing.

Okay, I think the ajax and async programs are few of the most difficult parts in front end.
The simple idea is that we have to keep the data source ready, and then use it.
However, the data source may come from database, http and etc.
How can we promise that the data is ready before starting to read it?

In this article, I will try to show the problem and how to use $q, deferred and promise to solve it.


Environment

l   AngularJS v1.4.8


▌Samples



Goals

I am going to create a DropDownList with dynamic options from database, through http get method.
So we will have an async method on the data source. To simplify the codes, I will use $timeout to simulate the http get method.

 

HTML :

<div ng-app="app" ng-controller="CustomerCtrl">
  <select ng-model="InCharge" ng-options="o.Title for o in CustomerOptions track by o.CustomerId" "></select></div>



Failed Attempt

The following js will results in nothing in the DropDownList.
The problem is that in the main thread :

$scope.CustomerOptions = CustomerFactory.InitCustomerOptions();

The method of factory is not thread-safe. It can’t promise you when the data will be took.

var app =
  angular.module('app', [])
  .factory('CustomerFactory', function ($q, $timeout) {

      var factory = {};

      factory.InitCustomerOptions = function () {
          var allOptions = [];

          $timeout(function () {

              //設定所有選項
              allOptions = [{
                  'CustomerId': '1',
                  'Title': 'JB'
              }, {
                  'CustomerId': '2',
                  'Title': 'Lily'
              }, {
                  'CustomerId': '3',
                  'Title': 'Leia'
              }, {
                  'CustomerId': '4',
                  'Title': 'Hachi'
              }, {
                  'CustomerId': '5',
                  'Title': 'Doogy'
              }];

              return allOptions;
          }, 3000);
      };

      return factory;
  })
  .controller('CustomerCtrl', function ($scope, $http, $q, CustomerFactory) {

      $scope.InCharge = {};

      //Initialize
      $scope.CustomerOptions = CustomerFactory.InitCustomerOptions();

  });




Correct Attempt

Now we use $q, deferred and promise to make sure that the data source is ready before reading it in the main thread.

Modify factory.InitCustomerOptions :

var getAllOptionsJob = $q.defer();
var getAllOptionsJobPromise = getAllOptionsJob.promise;

$timeout(function() {  //Async method to get the data source
    //returnObject =  …
    getAllOptionsJob.resolve(returnObject);
};
return getAllOptionsJobPromise;


Controller :

$scope.InCharge = {};

//Initialize
var getAllOptionsJobPromise = CustomerFactory.InitCustomerOptions();
getAllOptionsJobPromise.then(function (options) {
$scope.CustomerOptions = options;
   });
});




Reference




2015年12月17日 星期四

[AngularJS] DropDownList with ng-options

 AngularJS  


Introduction

Refers to

We have several ways to implement the DropDownList with AngularJS.

for array data sources:
label for value in array
select as label for value in array
label group by group for value in array
select as label group by group for value in array track by trackexpr
for object data sources:
label for (key , value) in object
select as label for (key , value) in object
label group by group for (key, value) in object
select as label group by group for (key, value) in object


However, I encountered some problems with it.
Here I will provide a correct way to make a DropDownList (<select> in HTML) with dynamic options and ng-model binding.


Environment

l   AngularJS v1.4.8




▌Samples



Goals

I want to create a DropDownList with dynamic options, which contains a “Please select” as default. When user select a different option excepts “Please select”, the label of the selected value will appear in the webpage.


Failed Attempt

Sounds easy, right? As a starter for AngularJS, I wrote something incorrect like the following codes. (See sample codes HERE)

<div ng-app="app" ng-controller="CustomerCtrl">
  <select ng-model="InChargeId" ng-change="ChangeChargeId()" ng-options="option.CustomerId as option.Title for option in CustomerOptions track by option.CustomerId" />
  <input type="text" ng-show="ShowCustomer" ng-model="InCharge" text="{{InCharge}}" />
</div>

And I try to control the selected value by writing :

$scope.InChargeId = 'Default';


So the result ends in like this …

Default value did not shown when initializing.



Selected value disappeared in the DropDownList



Correct Attempt

The most important thing is that we have to treat the option as an object!
The default value and other options are Objects, so as the ng-model of select.

Furthermore, remove option.CustomerId as …” when using “track by”.

This is the correct codes in HTML:

ng-options="option.Title for option in CustomerOptions track by option.CustomerId"

And use object reference to assign the default value! (JS)

$scope.InChargeId = $scope.CustomerOptions[0];




Reference




2015年12月12日 星期六

[AngularJS][Services] Service and Factory samples

 AngularJS  


Introduction

When things become complicated in the front end, we will try to organize our javascripts for reusing, sharing and maintainability.

In AngularJS, we can use $rootScope or Services , such like Service and factory, to achieve the above goals.


Environment

l   AngularJS v1.4.8




▌Samples



$rootScope

Explanation from AngularJS Documents :

Every application has a single root scope. All other scopes are descendant scopes of the root scope.


Sample Codes

l   root-scope.js

var app = angular.module('app')
.run(function ($rootScope) {

    $rootScope.WebSiteName = "MyWebSite";

});


l   my-controller.js

var app = angular.module('app', [])
.controller('RegisterCtrl', function ($scope,$rootScope) {
    var redirectUrl = window.location.origin + "/" + $rootScope.WebSiteName + "/Authentication/User";

});



Service

l   customer-service.js

var contactapp = angular.module('customerapp', []).
service('CustomerService', function ($http) {

    var GetAllCustomers = function () {

        return $http.get(getUri).error(function (status, headers, config) {
            console.log(status, headers, config);
        }).then(function (response) {
            return response;
        }).catch(function (e) {
            throw e;
        });
    };

    return GetAllCustomers;
});


l   my-controller.js

var app =
angular.module('app', ['customerapp'])
.controller('CustomerCreateCtrl', function ($scope, CustomerService) {
   
    var getPromise = CustomerService(); //For service
    getPromise.then(function (response) {

            angular.forEach(response.data, function (item) {
                var option = {};
                option.CustomerId = item.CustomerId;
                option.isEnabled = true;
                $scope.CustomerOptions.push(option);
            });

        }).catch(function (e) {
            swal("無法查詢所有客戶資訊,請稍後嘗試!", "", "error");
        })
});


Factory


var contactapp = angular.module('customerapp',[])
.factory('CustomerFactory', function ($http) {

    var factory = {};

    factory.KeyWords = 'Key words';

    factory.GetAllAvailableCustomer =
        function () {
              //return somthing
        };

    //Get
    factory.GetCustomer =
        function (inChargeId) {
             //return somthing
        };

    //Create
    factory.CreateCustomer =
        function (entity) {
             //return somthing
        };
    return factory;
});



var app =
angular.module('app', ['customerapp'])
.controller('CustomerCreateCtrl', function ($scope, CustomerFacory) {
     CustomerFactory.GetAllAvailableCustomer(); //For factory
     $scope.KeyWords = CustomerFactory.KeyWords;
});




Reference