Содержание

Пишем простую директиву в AngularJS

Директивы это киллер фича AngularJS. Они позволяют создавать многоразовые html елементы с своей собственной логикой внутри.

Вообще директивы в ангуларе считаются одной из самых крутых фич. Они позволяют легко инкапсулировать кусок кода в какой-то компонент, чтобы его потом переиспользовать. Одним из примеров директивы может быть календарь, написанный на JQuery, который легко можно инкапсулировать внутри директивы и потом использовать в любом месте нашего приложения.

Давайте рассмотрим как создаются директивы. Создадим div с атрибутом foo.

<div foo></div>

Как вы понимаете, такого атрибута в природе нет. Теперь в нашем js скрипт напишем

app.directive('foo', function () {
});

Директивы описываются специальным словом directive. Есть два варианта записи директив - короткий и полный. Короткий вариант, на самом деле, используется очень редко, но чтобы если вы его увидите, это вас не смущало, мы разберем сначала его.

app.directive('foo', function () {
    return function (scope, element, attrs) {
    };
});

В функцию создания директивы передается три параметра:

Что это такое? Scope - это область видимости данной директивы. Element - это DOM елемент нашей директивы, обернутый в JQlite и attrs - атрибуты этой директивы.

Давайте посмотрим. Для начала выведем console.log.

app.directive('foo', function () {
    return function (scope, element, attrs) {
        console.log('this is my directive');
    };
});

Если мы посмотрим в браузер, то увидим надпись this is my directive.

Теперь давайте выведем внутри директивы текст foo.

<div foo>foo</div>

Теперь мы видим наш DOM елемент на странице, но это уже не просто div, а директива. Вот этот атрибут foo, который мы задали, определяется этой директивой, и она срабатывает. То, что она срабатывает, мы видим, потому что у нас выводится console.log.

Теперь давайте изменим описание директивы на полное, которым обычно используется. Return будет возвращать не функцию, а обьект. Внутри этого обьекта у него есть проперти link, который в себе содержит функцию, которую мы писали ранее.

app.directive('foo', function () {
    return {
        link: function (scope, element, attrs) {
            console.log('this is my directive');
        }
    };
});

Что такое link? Link в директиве - это функция, которая срабатывает уже после того, как DOM елемент отрисовался на странице. Давайте теперь посмотрим, что такое scope, element и atts.

app.directive('foo', function () {
    return {
        link: function (scope, element, attrs) {
            console.log('scope', scope);
            console.log('element', element);
            console.log('attrs', attrs);
        }
    };
});

Передаваемые параметры

Если мы посмотрим в браузер, то увидим, что scope - это обьект, который является областью видимости нашей директивы. Element - это JQlite елемент, внутри него мы видим наш DOM елемент и attrs - это все атрибуты, которые есть на нашей директиве. Например, наш атрибут foo, который пустой, так как мы его не задали.

Что мы можем сделать с этой директивой? Мы можем на нее применить какие-то JQuery изменения, например.

app.directive('foo', function () {
    return {
        link: function (scope, element, attrs) {
            console.log('scope', scope);
            console.log('element', element);
            console.log('attrs', attrs);
            element.text('This is my magic directive');
        }
    };
});

Если мы посмотрим в браузер, то увидим текст This is my magic directive внутри директивы. Как мы видим, мы можем легко изменять елемент на что угодно после отрисовки. Давайте попробуем повесить ивент click на нашу директиву, чтобы при нажатии на нее надпись менялась с foo на bar, и обратно.

Для этого вешаем евент click и указывает функцию, которая будет происходить по клику.

app.directive('foo', function () {
    return {
        link: function (scope, element, attrs) {
            element.on('click', function () {
                console.log('click');
            });
        }
    };
});

Как мы видим, обычный клик отлично срабатывает.

Теперь давайте проверим, если текст елемента foo, то мы меняем его на bar.

app.directive('foo', function () {
    return {
        link: function (scope, element, attrs) {
            element.on('click', function () {
                if (element.text() === 'foo') {
                    element.text('bar');
                } else {
                    element.text('foo');
                }
            });
        }
    };
});

Повторим еще раз. Мы повесили на елемент click. И проверяем условие при клике. Если текст елемента равняется foo - мы меняем его на текст bar, в другом случае в текст елемента записываем foo.

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

<!DOCTYPE html>
<html lang="en" ng-app='app'>
<head>
    <meta charset="UTF-8">
    <title></title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.3.5/angular.min.js"></script>
  <script>
        var app = angular.module('app', []);
        app.controller('firstCtrl', function ($scope) {
 
        });
        app.directive('foo', function () {
            return {
                link: function (scope, element, attrs) {
                    element.on('click', function () {
                        if (element.text() === 'foo') {
                            element.text('bar');
                        } else {
                            element.text('foo');
                        }
                    });
                }
            };
        });
    </script>
</head>
<body>
<div ng-controller="firstCtrl" class="container">
    <div foo>foo</div>
    <div foo>foo</div>
    <div foo>foo</div>
    <div foo>foo</div>
    <div foo>foo</div>
    <div foo>foo</div>
</div>
</body>
</html>

Мы можем сколько угодно раз нажимать на каждый елемент и он будет менять текст.