Директива AngularJS для запоминания e-mail +4


Всем привет. Совсем недавно, в одном проекте понадобилось сделать «запоминание e-mail».

Требования простые: после того, как пользователь ввел e-mail, его нужно запомнить в cookie и автоматически заполнять при следующих обращениях к сайту.

AngularJS, не подвел! Решение получилось компактным и надеюсь, наглядным.

  1. В Javascript определяем директиву
  2. В html используем директиву чтобы указать что нужно «запомнить»

Для работы с cookie использовался jquery и плагин jquery-cookie.

Вот собственно демонстрация http://jsfiddle.net/dzb5rcsw/


Подробности


Дальше я буду разжевывать предложенное решение. Если заскучаете — переходите к коду в конце статьи.

IMHO самый лаконичный способ объявить какие e-mail должны запоминаться — это использовать директиву.

<body ng-app='habr-demo-app'>
    ...
    <input type='email' habr-remember-in-cookie='cookie-name-for-email1'/>
    ...
</body>


В моем случае использовался JSF, там объявление директивы немного отличается, но суть та же.

<h:inputText value="#{mybean.email}"
    pt:habr-remember-in-cookie="cookie-name-for-email1"/>


Директива


У меня уже был модуль AngularJS, поэтому я просто добавил к нему новую директиву. Но для демонстрации модуль придется создать.

Для начала обернем наш код в вызов анонимной функции (чтобы не захламлять глобальное пространство имен. А еще, потому, что так рекомендуют в Angular Style Guide https://github.com/johnpapa/angular-styleguide)

(function() {
    // Здесь будет наш код
)();


Затем объявим модуль и директиву

var app = angular.module('habr-demo-app', []);

app.directive('habrRememberInCookie', habrRememberInCookie);

function habrRememberInCookie() {
    function link(scope, element, attrs) {
    }
    return {
        restrict: 'A',
        link: link
    };
}


Как видите, никаких сложностей нет — все по документации AngularJS. От нас потребовалось только указать restrict: 'A' для того, чтобы директиву можно было использовать только как атрибут.

AngularJS вызывает функцию link для каждой директивы на странице. Про нее хорошо написано в документации.

В принципе весь церемониальный код уже написан, осталось написать саму функцию link. В ней нужно записать в поле ввода значение из cookie и настроить обработчик события change. При возникновении события change записываем новое значение в cookie.

function link(scope, element, attrs) {
    if(!element.val()) {
        var savedValue = $.cookie(attrs.habrRememberInCookie);
        element.val(savedValue);
    }
    element.on('change', function(event) {
        var newValue = element.val();
        $.cookie(attrs.habrRememberInCookie, newValue, {expires: 360});
    });
}


Вот так, все просто. По-хорошему нужно еще написать обработчик $destroy, но в приведенном примере в нем совершенно нечего делать. А вообще, он выглядит вот так.

element.on('$destroy', function() {
    console.log('Element deleted');
});


Код


HTML
<body ng-app='habr-demo-app'>
    <input type='email' habr-remember-in-cookie='cookie-name-for-email1'/>
</body>


JavaScript
(function() {
    var app = angular.module('habr-demo-app', []);
    
    app.directive('habrRememberInCookie', habrRememberInCookie);
    
    function habrRememberInCookie() {
        function link(scope, element, attrs) {
            if(!element.val()) {
                var savedValue = $.cookie(attrs.habrRememberInCookie);
                element.val(savedValue);
            }
            
            element.on('change', function(event) {
                var newValue = element.val();
                $.cookie(attrs.habrRememberInCookie, newValue, {expires: 360});
            });
        }
        return {
            restrict: 'A',
            link: link
        };
    }
})();

Спасибо за внимание. Критика приветствуется.




К сожалению, не доступен сервер mySQL