2
votes

I'm developing a web component form. I'm having troubles with angularjs bootsrap.

I'm creating dinamically a custom element with form.createdCallback <form> and <input, textarea etc> and adding ng-app="", ng-controller="" attributes. Later I encapsule it with template.createShadowRoot()

I use document.addEventListener('DOMContentLoaded', function(){angular.bootstrap(document, ['mform'])}), but doing this not execute anything from my angular app...

So, I tried removing the line template.createShadowRoot() and angular execute everything pretty well... so I arrived to the conclusion that the problem is angular not compiling inside shadow dom.

There's any hack or way to do this?

1

1 Answers

2
votes

I'm not sure if this really answers your question, but I am able to get Shadow DOM to work in Angular 1.x. Be aware that if you are after CSS encapsulation, then this will only work on browsers that natively support Shadow DOM since the Polyfill can not do the same thing.

I use $compile to create the contents of the Shadow DOM and bind that back into the directive.

Here is my code example:

<!DOCTYPE html>
<html ng-app="app">
  <head>
    <meta charset="utf-8">
    <title>Angular 1.x ShadowDOM example</title>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.6/angular.min.js"></script>
    <script>
    var app = angular.module('app', []);

    app.controller('myElController', ($scope) => {

    });

    var template = `
    <style>
    :host {
      left: 50%;
      position: fixed;
      top: 50%;
      transform: translate(-50%,-50%);
      border: 1px solid black;
      box-shadow: 4px 4px 4px rgba(0,0,0,.4);
      display: inline-block;
      padding: 6px 12px;
    }

    h3 {
      border-bottom: 1px solid #999;
      margin: 0 -12px 8px;
      padding: 0 12px 8px;
    }

    p {
      margin: 0;
    }
    </style>
        <h3>{{title}}</h3>
      <p>{{info}}</p>
    `;

    app.directive('myEl', ($compile) => {
        return {
          "restrict": "E",
          "controller": "myElController",
          "template": '',
          "scope": {
            "title": "@",
            "info": "@"
          },
          "link": function($scope, $element) {
            console.log('here');
            $scope.shadowRoot = $element[0].attachShadow({mode:'open'});
            $scope.shadowRoot.innerHTML = template;
            $compile($scope.shadowRoot)($scope);
          }
        };
    });
    </script>
  </head>
  <body>
    <div>
      <my-el title="This is a title" info="This is the info of the element"></my-el>
    </div>
    <div class="shell">
      <h3>Outside title (H3)</h3>
      <p>Outside content (P)</p>
    </div>
  </body>
</html>