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
      с трудом улавливаю язык автора, но идея хорошая.

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