Pull to refresh

Comments 15

Зря тянете целую jQuery + плагин для работы исключительно с печеньками, если все можно реализовать используя встроенный jqLite и angular-cookies. :)

Можно сделать вот так: embed.plnkr.co/QFYrwgLha5NAalWlXAjD/preview
Здесь я использую jquery-cookie для наглядности. Так как angular-cookie (когда я в последний раз на него смотрел) не позволяет кратко задать срок действия cookie.

В вашем примере (с использованием angular-cookie) testCookie является сессионным cookie. И при повторных входах пользователей значение не будет восстановлено. Такое решение мне не подходит.

В angular-1.4.0-beta.6 модуль angular-cookie уже доработан, поэтому когда он выпустится в релиз, можно будет отметить это здесь.
Да, вы правы насчет того, что в моем примере session cookie – я даже об этом не задумывался, если честно. Но это все фиксится дополнительным аргументом при установке cookie. И насчет модуля ngCookies вы совершенно верно дополнили, что нормальная реализация как раз с версии 1.4. В моем примере как раз и используется AngularJS 1.4.1. :)
Ммм… А вам реально там надо делать такую мелочь через какой-то суперсовременный фреймворк? Это же делается в 10 строк на обычном JS + немного jQuery.

Вот вам пример той же функциональности без всяких ангуляров: jsfiddle.net/dzb5rcsw/1

Ко всем нужным инпутам на странице добавляем атрибут saveable, и уаля: отныне его значение будет всегда сохраняться в куках и восстанавливаться при обновлении страницы.
Я так понимаю что AngularJS уже был в проекте, вот автор и использовал его.
Одна разница:
в ангуляре потом очень легко найти и подправить (если нужно), этот функционал. А эти хандлеры для jQuery утонут в тоннах такого же неструктурированного кода.
Хороший код. Вот что бы я еще с ним сделал:

— для наглядности я бы прописал имя куки в атрибут saveable (и чтобы отвязаться от имени поля в именах кук)
— исправил ошибку с восстановлением значения только в случае если поле не заполнено
— и пожалуй переименовал бы атрибут во что-нибудь вроде save-to-cookie (или data-my-save-to-cookie)

jsfiddle.net/dzb5rcsw/2

Получился отличный jQuery код. От решения на AngularJS отличается только тем, что здесь код помещается в общую кучу, а в AngularJS он оформляется во вполне определенный компонент (директиву), и немного лучше подходит для повторного использования или модульного тестирования.

Нужен ли AngularJS ради такой мелочи?

А если таких мелочей хотя бы штук 5? Тогда в AngularJS будет 5 простых директив, а в JQuery 10 фрагментов. Которые со временем мигрируют в один блок $(document).ready(funtion() {}); и будет потеряна возможность модульного тестирования каждого фрагмента по отдельности.
Чтобы не смешивать в одной куче такие небольшие кусочки JS-кода, я обычно размещаю каждый из них в своём отдельном js-файле, а также помещаю весь функционал в отдельную родительскую js-функцию с ясным названием. Таким образом, можно сказать, мы создаём свой компонент на чистом JS. По моему личному опыту, в 90% случаев этого более чем достаточно.

В данном нашем случае мы можем написать, скажем, компонент под названием SaveableInputs, поместить его в отдельный js-файл под названием saveable-inputs.js, и если понадобится, позже спокойно рефакторить и дорабатывать его. А впоследствии его можно будет даже залить на гитхаб и спокойно подключать его последние версии через bower ко всем своим проектам, нуждающимся в подобном функционале :)

Вот пример кода данного компонента: jsfiddle.net/dzb5rcsw/11

При необходимости, мы также можем вызвать метод SaveableInputs.loadFromCookies() из любого места нашего приложения (в том числе и где-то в ангуляровском коде). Например, после динамичной подгрузки и отображения какой-то формы, чтобы попытаться заполнить её поля.

И еще, насчёт названий кук. Я не согласен с вами. Автоматически генерировать название куки удобнее, особенно если этих инпутов у вас будет много на странице. Еще это не даст запутаться. Правда, если у вас на странице будет два инпута с одинаковым значением name, то заполнятся оба из них одним и тем же текстом… Ну тогда уж всегда можно будет доработать компонент)

Я, кстати, как вы наверное заметили, не использую некоторые известные методы jQuery, вроде el.val() и el.attr(). Просто стараюсь иногда почитывать документацию ванильной JS и использовать её, благо сейчас необходимость в jQuery-методах уже практически отпала: все браузеры уже давно реализовали и поддерживают основную JS-спецификацию, и её можно спокойно использовать как основу для работы с JS.
А вам действительно нужен jQuery? Тем более только для связи с печеньками и подстановкой в инпут? Почему бы не написать на пару строк больше и сделать независимый функционал.
Ну как сказать) Согласитесь: на текущий 2015-й год jQuery имеется на подавляющем большинстве современных сайтов. Это первая причина, по которой нет особого смысла полностью от него отказываться. Вторая причина заключается в том, что есть множество сторонних плагинов и библиотек, прекрасно дополняющих jQuery и — опять же, — не способных работать без него. Третья причина заключается в том, что вместе с ним наш код, всё-таки, как ни крути, но становится более простым и лаконичным. Четвёртая причина заключается в том, что свои велосипеды редко получаются реально хорошо написанными и понятными другим разработчикам, и его будет труднее поддерживать. Пятая причина заключается в том, что jQuery и его плагины уже были протестированы большим сообществом, что не скажешь о моих (и ваших) велосипедах.

Но если вы реально гуру Javascript и можете писать крутой и лёгкий для восприятия код без jQuery — тогда конечно можно попробовать. Но я о себе такое врятли смогу сказать. Хоть я и написал уже кучу всего на JS, всё равно не считаю себя великим знатоком данного языка.

Ну так вот, подводя итоги… Какой смысл отказываться полностью от данного удобного инструмента, если отказаться от него всё равно будет очень трудно, да и пользы особой от этого не будет? Да и не будем мы тратить своё личное время только ради того, чтобы потенциально сделать проект чуть более легким и независимым (да и не факт совсем, что это у нас получится).

Поэтому, ладно уж. Пусть будет и немного jQuery :)
Если подключить ng-model то перестает работать в Chrome.

Почему Cookie, а не localStorage?
Чтобы при перехвате трафика могли пользователей распознавать.
О, это хороший вопрос! Как это сделать технически уже показал AMar4enko.

А вот с точки зрения архитектуры…
Если есть модель данных, то начальные значения этих данных должны определяться в том месте где эта модель создается (или там где заполняется — если данных загружаются асинхронно). Получается, что в случае, когда поле ввода «привязано» к модели данных с помощью ng-model конструкция habr-remember-in-cookie окажется вредной :-(

Особенный вред проявится, если данные для модели загружаются асинхронно. М-да… спасибо, критика оказалась полезной.

Версия с поддержкой ngModel. Писал навскидку, мог где-то ошибиться.
Также поддержка интерполяции внутри атрибута и сохранение в куку, только если введенный текст — email.

(function() {
    var app = angular.module('habr-demo-app', []);
    
    app.directive('habrRememberInCookie', habrRememberInCookie);
    
    function habrRememberInCookie($interpolate) {
        function link(scope, element, attrs, ngModel) {
            var cookieName = $interpolate(attrs.habrRememberInCookie)($scope); 
            if(ngModel) {
                if(!ngModel.$viewValue) {
                    ngModel.$setViewValue($.cookie(cookieName));
                }
                ngModel.$viewChangeListeners.push(function(value) {
                    if(!ngModel.$error.email){
                        setCookieValue(value);    
                    }
                }); 
                 
                return;  
            }

            if(!element.val()) {
                var savedValue = $.cookie(cookieName);
                element.val(savedValue);
            }
            
            element.on('change', function(event) {
                var newValue = element.val();
                setCookieValue(newValue);
            });
            
            function setCookieValue(value) {
               $.cookie(cookieName, value, {expires: 360}); 
            } 
        }
        return {
            restrict: 'A',
            require: '?ngModel',
            link: link
        };
    }
})();
Почему не Cookie/localStorage/sessionStorage/…?

Мне кажется, что код сохранения/изъятия значения из хранилища стоит вынести в отдельный сервис, который будет подключаться через Dependency Injection, так его можно будет легко подменить, что упростит переиспользование кода.
Sign up to leave a comment.

Articles