Как передать шаблон через привязки к компоненту AngularJS

Я хотел бы передать пользовательский шаблон через привязки в компонент AngularJS и отобразить его, используя его область. Что-то вроде этого (псевдокод, это не работает):

angular
  .module('myApp', [])
  .controller('mainController', ($scope) => {

    $scope.getTemplate = () => (`
      <div>
        <span>{{$ctrl.name}}</span>
      </div>
    `)
  })
  .component('myComponent', {
    controller: ($scope, $compile) => {
      const $ctrl = $scope.$ctrl;

      $ctrl.$onInit = () => {
        $ctrl.name = 'Hello World!';
      };

      $ctrl.compileTemplate = () => $compile($ctrl.template())($scope);
    },
    bindings: {
      template: '&'
    },
    template: `
      <div>
        My dynamic content: {{$ctrl.compileTemplate()}}
      </div>
  `
  });

Использование:

<div ng-controller="mainController as $ctrl">
  <my-component template="$ctrl.getTemplate()"></my-component>
</div>

Ожидаемый результат:

<div>
  My custom content:
  <div>
    <span>Hello World!</span>
  </div>
</div>

Есть ли способ сделать это?


person mattias    schedule 21.09.2017    source источник


Ответы (2)


Если вам нужен динамический шаблон, вы можете использовать тот факт, что вы можете передать функцию компоненту template, в компонентах, которые можно вводить, я отсылаю вас к этот вопрос для получения дополнительной информации, но вот основная идея:

angular
  .module('myApp', [])
  .factory('tempalteFactory', {
      return getTemplate() {
          retrun '<b> yep </b>';
      }
  })
  .component('myComponent', {
    controller: ($scope, $compile) => {
      const $ctrl = $scope.$ctrl;

      $ctrl.$onInit = () => {
        $ctrl.name = 'Hello World!';
      };   

    },
    template: function($element, $attrs, templateFactory) {
          'ngInject';

          return templateFactory();
    }    
  });
person Rathma    schedule 21.09.2017
comment
Спасибо, но я хочу внедрить область действия директивы в шаблон. - person mattias; 23.09.2017
comment
Что вы имеете в виду, вводя область в шаблон? шаблон компилируется в соответствии с областью, поэтому на основе области он оценивается в соответствии с вашей привязкой my или может не работать. - person Rathma; 23.09.2017
comment
Я имею в виду, что в вашем примере у вас есть шаблон, переданный привязкой, скомпилированной с областью действия, которую я хочу в var compileTemplate, но вы возвращаете templateFactory - person mattias; 23.09.2017
comment
не уверен, зачем вам это нужно, если вы подробнее остановитесь на своей проблеме, возможно, я смогу вам помочь, но я думаю, вы можете превратить этот общий шаблон в другую директиву и использовать ng-switch или ng-if в своем компоненте... - person Rathma; 23.09.2017
comment
Мне нужно создать компонент, который получает набор элементов и шаблон. Он будет перебирать все элементы (с ng-repeat) и отображать собственный шаблон для каждого из них. - person mattias; 23.09.2017
comment
если вы измените свой исходный пример, чтобы использовать ng-bind-html или его небезопасный вариант, я думаю, вы готовы использовать свое решение, но что мне приходит в голову, так это иметь директиву элемента, которая отображается по-разному на основе предоставленного ему шаблона. - person Rathma; 23.09.2017
comment
Не могли бы вы поделиться рабочим примером? Потому что мой не работает - person mattias; 23.09.2017

Вы можете использовать службу $compile для создания директивы для обработки манипуляций с DOM. вовлеченный.

Следующий рабочий фрагмент реализует директиву атрибута compile, которая компилирует входное значение атрибута в области действия контроллера. По сути, он берет ваш шаблон и добавляет его во внутреннее содержимое элемента, к которому прикреплена директива, и, наконец, компилирует его.

angular.module('app', [])
  .run(($rootScope) => {  
    $rootScope.name = 'world';    
    $rootScope.template = `
      <label>Name</label>
      <input type="text" ng-model="name">
      <h2>Hello {{ name }}!</h2>
    `;
  })
  .directive('compile', ($compile) => {
    return (scope, element, attrs) => {
      scope.$watch(
        scope => scope.$eval(attrs.compile),
        value => {
          element.html(value);
          $compile(element.contents())(scope);
        }
      );
    };
  })
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.5/angular.js"></script>
<div ng-app="app">
  <div compile="template"></div>
</div>

person lenilsondc    schedule 21.09.2017
comment
Я хочу ввести в шаблон область действия директивы. Вы можете увидеть это на моем примере - person mattias; 23.09.2017
comment
@mattias хорошо, вам просто нужно добавить директиву в свой шаблон <div compile="$ctrl.getTemplate()"></div> - person lenilsondc; 23.09.2017
comment
Я хочу сделать это с помощью компонента вместо директивы - person mattias; 24.09.2017
comment
вы можете делать все, что компоненты делают с директивами, компоненты являются более ограниченным типом директив, поэтому вы не можете компилировать с компонентами, поэтому директивы - это путь. Что именно вы хотите сделать с компонентами? - person lenilsondc; 25.09.2017