Angular Light. Управляем декларативным биндингом данных в HTML

    В angular есть 2 инструмента вывода информации в DOM — это директивы и декларативный биндинг данных в HTML {{model}}.
    В то время когда директивы обладают большими возможностями, декларативный биндинг немного ограничен, он делает $watch на модель с возможностью вызвать фильтры и по большому счету — все. А хотелось бы больше гибкости.

    Например если посмотреть на библиотеку bindonce для Angular.js, основная идея — это разовый вывод информации без использования $watch.
    И для того что-б её можно было использовать в любом месте, для любого атрибута, разработчик сделал ряд отдельных директив: bo-text, bo-href-i, bo-href, bo-src-i, bo-src, bo-class, bo-alt, bo-title, bo-id, bo-style, bo-value, bo-attr и bo-attr-foo. Но по сути, все они делают одно и тоже и по логике это должна быть одна директива.
    Так же это отклоняется от декларативного биндинга данных, задуманного в Angular.js, т.е. вместо
    <a href="{{link}}">{{name}}</a>
    
    нужно писать
    <a bo-href-i="{{link}}" bo-text="name"></a>
    
    Т.е. для чего был придуман декларативный биндинг данных, в этой ситуации не работает.

    Поэтому появилась идея реализовать директивы для декларативного биндинга данных.
    Как это работает в Angular Light — просто нужно указать имя директивы и перед этим поставить знак "#", т.е. вместо {{model}} будет {{#directive model}}.
    Бесполезный, но простой пример счетчика:
    <div al-app>
        counter {{#counter model}}
    </div>
    
    Делаем биндинг «model» и подключаем директиву «counter», для простоты я опустил использование «model» в данной директиве:
    alight.text.counter = function(callback, expression, scope, env) {
        var n = 0;
        setInterval(function(){
            n++;
            callback(n)  // set result
            scope.$scan()  // $digest
        }, 1000);
    }
    
    На входе у директивы мы получаем:
    • callback — ф-ия для отправки текста в местоположение биндига
    • expression — входное выражение биндинга, в данном случае это «model»
    • scope — текущий Scope
    • env — ссылка на «внутренности» биндинга и для расширения функционала
    Пример как это работает

    Далее пример со вставкой биндига в атрибуты, директива loadLoginById которая «имитирует» загрузку данных с сервера:
    <div al-app al-init="user_id = '555'">
        id = <input type="text" al-value="user_id" /> <br/>
        into href = <a href="http://example.com/?search={{#loadLoginById user_id}}">user's page</a> <br/>
        into title = <span title="{{#loadLoginById user_id}}">user</a> <br/>
        into text = {{#loadLoginById user_id}}
    </div>
    
    Пример

    Ну и напоследок пример с bindonce, одна директива которая заменяет 11 из bind-once библиотеки:
    <div al-app al-init="link = 'google.com'">
        id = <input type="text" al-value="link" /> <br/>
        usual, with $watch = <a href="http://{{link}}">{{link}}</a> <br/>
        bindonce = <a href="http://{{#bindonce link}}">{{#bindonce link}}</a> <br/>
        aliase of bindonce = <a href="http://{{=link}}">{{=link}}</a> <br/>
    </div>
    
    Пример

    Если декларативный биндинг придуман для удобного вывода информации, почему бы его не использовать по полной?
    Поделиться публикацией
    Похожие публикации
    Ммм, длинные выходные!
    Самое время просмотреть заказы на Фрилансим.
    Мне повезёт!
    Реклама
    Комментарии 1
    • +2
      с трудом улавливаю язык автора, но идея хорошая.

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