Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

When using $compile on component, why is the scope passed through $parent?

I'm trying to dynamically compile an Angular component using $compile, but the scope isn't passed to the components scope, but to the $parent scope instead.

Here is a simple component that binds to a myTitle-attribute and presents it:

app.component('myComponent', {
  bindings: {
    myTitle: '<'
  },
  template: `
    <div>
      <div>Doesn't work: {{ $ctrl.myTitle}}</div>
      <div>Works: {{ $parent.$ctrl.myTitle}}</div>
    </div>`
});

Then in the controller (or directive, etc.) I compile it using $compile:

app.controller('MainCtrl', function($scope, $element, $compile) {
  var template = '<my-component></my-component>';
  
  var bindings = {
    myTitle: 'My Title'
  }
  var scope = angular.extend($scope.$new(true), {
    $ctrl: bindings
  });
  var newElement = $compile(template)(scope);
  $element.append(newElement);
  
});

When running this, it yield the result:

Doesn't work:

Works: My Title

Here's a plunker showing it in action

The question

How come the scope I create for the dynamically created component, is passed as a parent scope of the component?

Any pointer on why angular behaves like this and perhaps how to avoid it is much welcome.

like image 793
Nikolaj Dam Larsen Avatar asked May 30 '17 12:05

Nikolaj Dam Larsen


1 Answers

As I see, you need to pass binding here var template = '<my-component></my-component>';

var template = '<my-component my-title="$ctrl.myTitle"></my-component>';

Full component may be like this:

app.controller('MainCtrl', function($scope, $element, $compile) { 
  var template = '<my-component my-title="$ctrl.myTitle"></my-component>'; 
  $scope.$ctrl = {myTitle: 'My Title'}; 
  $element.append($compile(template)($scope)); 
});
like image 176
John Doe Avatar answered Oct 06 '22 05:10

John Doe