0

I add DOM element (externally to Angular), $compile it and link it with scope in directive's event handler - controller defined in ng-controller of new element fires up, but databinding is not working - the result is

{{data.name}}

like it's not compiled at all ... Why? (I use $compile for the first time so, maybe I'm missing something)

Below is just directive's code:

app.directive('pages', function ($compile) {
  return {
    restrict: 'E',
    link: function (scope, element) {
      element.on('pageLoaded', function(event){
        var page = angular.element(event.detail.element);

        var linkFn = $compile(page);

        scope.data = {
          name: 'DATA SET IN DIRECTIVE'
        };

        linkFn(scope);
      });
    }
  }
});

Page I add (dom element in event.detail.element) is

<div page="AddedPage" ng-controller="PageController">
{{data.name}}
</div>

Here is jsfiddle: http://jsfiddle.net/yoorek/EYCwY/

Yoorek
  • 1,003
  • 1
  • 12
  • 30

2 Answers2

0

Add addPage into controller and use ng-click

http://jsfiddle.net/EYCwY/1/

<div ng-app="app" ng-controller="AppController">
<button ng-click="addPage()">Add Page</button>
<pages>
    <page page="StaticPage">
    </page>
</pages>

app.controller('AppController', function ($scope) {
  log('App Controller');

  $scope.data = {
    name: 'Data set in AppController'
  }

  $scope.addPage = function () {
  var page = document.createElement('div');
  var parent = document.getElementsByTagName('pages')[0];

  page.setAttribute('page', 'AddedPage');
  page.setAttribute('ng-controller', 'PageController');
  page.innerHTML = '{{data.name}}';

  parent.appendChild(page);

  var event = new CustomEvent(
      "pageLoaded",
      {
        detail: {
          page: "AddedPage",
          element: page
        },
        bubbles: true,
        cancelable: true
      }
  );

  parent.dispatchEvent(event);
};
});
Slaven Tomac
  • 1,552
  • 2
  • 26
  • 38
  • It is not recommended to do DOM manipulations in the controller. This makes for code you can not reuse or test: the controller is highly coupled with the view rather than communicating through the scope and events. – Steve Klösters May 09 '14 at 09:25
  • that's true...that's a BIG NO...I just wanted to make his code work :) – Slaven Tomac May 09 '14 at 09:29
  • @stevuu - i hope you understand that's just quick a sample not production code? :-))) – Yoorek May 09 '14 at 10:28
  • @SlavenTomac - you changed mechanism of adding pages : first - that was just sample to illustrate problem, second - it's not gonna work - pages are generated and inserted externally to angular bootstrapped application - what i can do is just send standard event nothing more. solution with replaceWith works anyway. – Yoorek May 09 '14 at 11:04
0

You didn't add the element to the DOM. See this Fiddle:

scope.$apply(function () {          
    element.replaceWith($compile(page)(scope));
});

If you want to add multiple pages, append it instead of replacing it.

Furthermore, I recommend reading through this post on the recommendations and concepts of AngularJS.

Community
  • 1
  • 1
Steve Klösters
  • 9,427
  • 2
  • 42
  • 53
  • Thanks for solution - made a stupid mistake :-) recommended reading know by heart but it has nothing to do with project i'm working on - very specific case of pages that appear in external library which cannot be changed, looking for solution to igrate these solutions somehow. – Yoorek May 09 '14 at 10:26
  • Sounds good! I didn't know there were project constraints. When I see a lot of jQuery "frameworking" in combination with AngularJS I usually link to the linked post, just for reference. – Steve Klösters May 09 '14 at 10:28
  • Hmmm... there is a problem though - replacewith makes two way databinding not working. when used append instead databinding works - here is codepen : http://codepen.io/yoorek/pen/kcFqJ . when you change replaceWith with append you see it works. any idea why? – Yoorek May 09 '14 at 19:51
  • I got it working - inserting newly compiled and linked element is not necessary, scope.$apply is enough - http://codepen.io/yoorek/pen/kcFqJ – Yoorek May 09 '14 at 20:14