Здесь показаны различия между двумя версиями данной страницы.
| Следующая версия | Предыдущая версия | ||
|
angular:angularjs:custom_directive:transclude_element [2020/06/15 22:53] werwolf создано |
angular:angularjs:custom_directive:transclude_element [2023/01/12 12:18] (текущий) |
||
|---|---|---|---|
| Строка 1: | Строка 1: | ||
| =====Transclude element в директивах AngularJS===== | =====Transclude element в директивах AngularJS===== | ||
| - | **transclude: ‘element’** - трансклюдирует весь элемент, и функция связывания трансклюда вводится в функцию компиляции. Вы не можете иметь доступ к области здесь, потому что область еще не создана. Compile function создает функцию связи для директивы, которая имеет доступ к scope, и transcludeFn позволяет коснуться клонированного элемента (который был трансклинирован) для манипуляции DOM или использовать данные, привязанные к scope в нем. Для вашего сведения, это используется в ng-repeat и NG-switch. | + | <note> |
| + | **transclude: ‘element’** - трансклюдирует весь элемент, и функция связывания трансклюда вводится в функцию компиляции. Вы не можете иметь доступ к области здесь, потому что область еще не создана. Compile function создает функцию связи для директивы, которая имеет доступ к scope, и transcludeFn позволяет коснуться клонированного элемента (который был трансклинирован) для манипуляции DOM или использовать данные, привязанные к scope в нем. Для вашего сведения, это используется в ng-repeat и NG-switch.\\ | ||
| + | </note> | ||
| + | |||
| + | Попробуем разобраться что такое **transclude: element** и как оборачивать директиву в дополнительную разметку.\\ | ||
| + | |||
| + | Для начала создадим форму.\\ | ||
| + | <code javascript> | ||
| + | <form> | ||
| + | <div> | ||
| + | <label>Email:</label> | ||
| + | <input type="text" placeholder="Place your email"> | ||
| + | </div> | ||
| + | <div> | ||
| + | <label>Password:</label> | ||
| + | <input type="password" placeholder="Enter your password"> | ||
| + | </div> | ||
| + | <button>Submit</button> | ||
| + | </form> | ||
| + | </code> | ||
| + | |||
| + | Мы будем добавлять директиву на елемент формы. Назовем директиву wrap-in и передадим параметр red.\\ | ||
| + | <code javascript> | ||
| + | <form wrap-in="red"> | ||
| + | </form> | ||
| + | </code> | ||
| + | |||
| + | Давайте создадим директиву | ||
| + | <code javascript> | ||
| + | app.directive('wrapIn', function () { | ||
| + | return { | ||
| + | link: function (scope, element, attrs) { | ||
| + | console.log('wrapIn'); | ||
| + | } | ||
| + | }; | ||
| + | }); | ||
| + | </code> | ||
| + | |||
| + | В консоли у нас вывелось wrapIn. | ||
| + | {{ :angular:angularjs:custom_directive:directive27.png |}} | ||
| + | |||
| + | Теперь добавим поле transclude. | ||
| + | |||
| + | <code javascript> | ||
| + | app.directive('wrapIn', function () { | ||
| + | return { | ||
| + | transclude: 'element', | ||
| + | link: function (scope, element, attrs) { | ||
| + | console.log('wrapIn'); | ||
| + | } | ||
| + | }; | ||
| + | }); | ||
| + | </code> | ||
| + | |||
| + | Как мы видим в браузере, весь контент у нас пропал. Давайте напишем текст до формы, чтобы видеть что происходит | ||
| + | |||
| + | <code> | ||
| + | My form here | ||
| + | </code> | ||
| + | |||
| + | Как мы видим, в инспекте елементов есть надпись** "My form here"**, а дальше идет комментарий **wrapIn: red**. Когда мы используем transclude, то у нас остается такой комментарий, чтобы было видно, что здесь должна применятся директива.\\ | ||
| + | |||
| + | {{ :angular:angularjs:custom_directive:directive28.png |}} | ||
| + | |||
| + | Теперь давайте передадим в линк функцию пятым параметром transclude. | ||
| + | |||
| + | <code> | ||
| + | link: function (scope, element, attrs, ctrl, transclude) { | ||
| + | console.log('wrapIn'); | ||
| + | transclude(scope, function (clone) { | ||
| + | console.log(clone); | ||
| + | }); | ||
| + | } | ||
| + | </code> | ||
| + | Мы вызвали функцию transclude с пераметром scope и функцией, где первым параметром идет clone.\\ | ||
| + | \\ | ||
| + | В консоли мы видим,что clone - это наша форма, которая сейчас находится в transclude. Как мы видим, это полностью наш елемент, на который мы повесили директиву. Не его содержимое, а весь елемент. Это главное отличие **transclude = element** от **transclude = true**.\\ | ||
| + | \\ | ||
| + | Теперь давайте создадим в body script. | ||
| + | <code javascript> | ||
| + | <script type="text/ng-template" id="red"> | ||
| + | <div class="red"></div> | ||
| + | </script> | ||
| + | </code> | ||
| + | |||
| + | Зачем мы это делаем? Мы хотим потом в директиве из templateCache достать шаблон.\\ | ||
| + | |||
| + | Теперь давайте в нашу директиву заинджектим templateCache. | ||
| + | <code javascript> | ||
| + | app.directive('wrapIn', function () { | ||
| + | return { | ||
| + | transclude: 'element', | ||
| + | link: function (scope, element, attrs, ctrl, transclude) { | ||
| + | var template = $templateCache.get(attrs.wrapIn); | ||
| + | console.log('wrapIn', template); | ||
| + | transclude(scope, function (clone) { | ||
| + | console.log(clone); | ||
| + | }); | ||
| + | } | ||
| + | }; | ||
| + | }); | ||
| + | </code> | ||
| + | |||
| + | attrs.wrapIn берет аргумент директивы wrap-in и означает red. В скрипте у нас id нашего шаблона red. То есть мы хотим из templateCache выгрести шаблон с id red.\\ | ||
| + | В консоли вывелся наш шаблон. | ||
| + | {{ :angular:angularjs:custom_directive:directive29.png |}} | ||
| + | |||
| + | Теперь мы хотим сгенерировать новый елемент. | ||
| + | |||
| + | <code javascript> | ||
| + | app.directive('wrapIn', function ($templateCache) { | ||
| + | return { | ||
| + | transclude: 'element', | ||
| + | link: function (scope, element, attrs, ctrl, transclude) { | ||
| + | var template = $templateCache.get(attrs.wrapIn); | ||
| + | var templateElement = angular.element(template); | ||
| + | transclude(scope, function (clone) { | ||
| + | element.after(templateElement.append(clone)); | ||
| + | }); | ||
| + | } | ||
| + | }; | ||
| + | }); | ||
| + | </code> | ||
| + | |||
| + | В templateElement будет уже записан не string, а созданный DOM елемент. Далее в наш елемент, который пустой, так как срабатывает transclude добавляем templateElement и внутрь аппендим clone. clone как вы помните - это наша форма.\\ | ||
| + | В браузере мы видим, что наша форма выводится. И мы видим, что у нас красные стили из-за того, что все форма обернута в класс red.\\ | ||
| + | |||
| + | {{ :angular:angularjs:custom_directive:directive30.png |}} | ||
| + | |||
| + | Так очень легко оборачивать директиву в какой-то нужный вам контент. Давайте создадим еще один скрипт с id=table.\\ | ||
| + | В директиве wrap-in передадим параметр table. | ||
| + | <code javascript> | ||
| + | <!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.7.9/angular.min.js"></script> | ||
| + | <style type="text/css"> | ||
| + | .red{ | ||
| + | color: red; | ||
| + | } | ||
| + | </style> | ||
| + | <script> | ||
| + | var app = angular.module('app', []); | ||
| + | |||
| + | app.directive('wrapIn', function ($templateCache) { | ||
| + | return { | ||
| + | transclude: 'element', | ||
| + | link: function (scope, element, attrs, ctrl, transclude) { | ||
| + | var template = $templateCache.get(attrs.wrapIn); | ||
| + | var templateElement = angular.element(template); | ||
| + | transclude(scope, function (clone) { | ||
| + | element.after(templateElement.append(clone)); | ||
| + | }); | ||
| + | } | ||
| + | }; | ||
| + | }); | ||
| + | </script> | ||
| + | </head> | ||
| + | <body> | ||
| + | <script type="text/ng-template" id="red"> | ||
| + | <div class="red"></div> | ||
| + | </script> | ||
| + | <script type="text/ng-template" id="table"> | ||
| + | <div>Header for table</div> | ||
| + | </script> | ||
| + | <form wrap-in="table"> | ||
| + | <div> | ||
| + | <label>Email:</label> | ||
| + | <input type="text" placeholder="Place your email"> | ||
| + | </div> | ||
| + | <div> | ||
| + | <label>Password:</label> | ||
| + | <input type="password" placeholder="Enter your password"> | ||
| + | </div> | ||
| + | <button>Submit</button> | ||
| + | </form> | ||
| + | </body> | ||
| + | </html> | ||
| + | </code> | ||
| + | |||
| + | В браузере мы видим, что у нас вывелся дополнительный контент перед формой. Это тоже удобно, когда мы можем сгенерировать часть контента вне директивы, а потом просто сгенерировать шаблон.\\ | ||
| + | |||
| + | {{ :angular:angularjs:custom_directive:directive31.png |}} | ||
| + | |||
| + | Главное, что вы должны заполнить из этого видео, что transclude = element позволяет делать transclude всей директивы сразу. Не содержимого блока, а всего блока. | ||