mmm
mmm

Reputation: 2297

Update directive after adding elements dynamically

What I want to do:

Use directives to create custom elements, and be able to dynamically add those elements into the view at different times.

The Problem:

When I add custom elements dynamically into the view, the elements appear as html inside the view, but the directive doesn't update the elements like it's supposed to.

For Instance:

We have a custom element -> <ell></ell>. When I include <ell></ell> in the raw html, the directive works as expected and fills it with 4 divs, each with a class of 'block'. Like so -> <div class="block"></div>.

But if I set the HTML of a div -> <div id="level" ng-bind-html="piecesInPlay"></div> as equal to a string inside the controller, and update that string, the directive doesn't act on the <ell></ell> tag.


Here's the relevant code:

Angular Directives: (there's one directive for each element in scp.pieces[] below)

app.directive('sqr', function() {
  return {
    restrict: 'E',
    template: tetris.templateString,
    link: tetris.randColor
  };
});

Angular Controller:

app.controller('levelCtrl', ['$scope', function(scp) {
  scp.pieces = ['<ell></ell>', '<r-ell></r-ell>', '<sqr></sqr>', '<zee></zee>', '<r-zee></r-zee>', '<tee></tee>', '<line></line>'];
  scp.piecesInPlay = '<ell></ell>';
  
  scp.generateNewPiece = function() {
    var min = 0, max = 6;
    var randPiece = Math.floor(Math.random() * (max - min + 1)) + min;
    
    scp.piecesInPlay += scp.pieces[randPiece];
    return scp.pieces[randPiece];
  };
  
  // generates a random piece and adds it to the pieces in play
  scp.generateNewPiece();
}]);

HTML:

<div id="level" ng-controller="levelCtrl" ng-bind-html="piecesInPlay">
    
</div>

Upvotes: 1

Views: 1003

Answers (1)

FlavorScape
FlavorScape

Reputation: 14289

1) While the function returns a string, it does nothing with it. return scp.pieces[randPiece];

2) You have to compile the string into an element and append it.

     var newElement= $compile(template)($scope);
     $element.append( element );
     $scope.$digest();

you need to compile it for angular to recognize the new directive you've jammed in there, and then you have to digest because that will downward propagate the command for child scopes to start.

UPDATE:

Based on the comments, the question is getting after an ability to bind to compiled "directive elements" in the DOM from an array, and have the page update without appending and digesting a new scope, as if we are invoking controllers directly from HTML strings.

I don't think this is possible, directly. You'd be better off having an array of strings with the controller names of your game pieces.

Then in your ng-repeat, manually bind a controller based on that string.

<div class="my-pieces" ng-repeat="controllerName in board.activeControllerStrings">

<div ng-controller="{{controllerName}}"></div>

That way you get live data binding, and you skip the directive part and manually jam some controller functionality into the elements.

Upvotes: 1

Related Questions