1

I am trying to create a pop up dialog with two buttons created in JS code with angular. The following code that produces the buttons...

var html = $('<button ng-click = "cancelAlert()" > Cancel</button > <button ng-click="continueAlert()">Continue</button>');
var div = $compile(html);
var content = div($scope);
document.getElementById('dialogboxhead').innerHTML = "header";
document.getElementById('dialogboxbody').innerHTML = "body";
document.getElementById('dialogboxfoot').innerHTML = content;

Gives me the following html text instead of the actual buttons themselves...

[[object HTMLButtonElement], [object Text], [object HTMLButtonElement]]

Am I missing something here that I have forgotten to add in?

The HTML looks like the following...

<div id="dialogoverlay"></div>
<div id="dialogbox">
    <div>
        <div id="dialogboxhead"></div>
        <div id="dialogboxbody"></div>
        <div id="dialogboxfoot"></div>
    </div>
</div>
georgeawg
  • 48,608
  • 13
  • 72
  • 95
Casey Daly
  • 383
  • 8
  • 25
  • You're trying to do this in a controller? I don't think you can - you have to use `$compile` in a directive. If you really need to use it outside a directive you can take a look at [this question](https://stackoverflow.com/questions/22370390/how-can-we-use-compile-outside-a-directive-in-angularjs). – Lex Aug 23 '18 at 22:14

2 Answers2

2

The $compile method accepts a string argument if you want to provide markup in this way.

Avoid wrapping the input for $compile with anything (ie $(..)). Instead, just pass the html string directly to the $compile() method, and also attach the div via the DOM append() method, and you should find this will work as expected:

var html = '<button ng-click="cancelAlert()">Cancel</button><button ng-click="continueAlert()">Continue</button>';
var div = $compile(html);
...
document.getElementById('dialogboxfoot').append( div[0] );

For more infromation see the usage on the official docs.

Here's a link to a working jsFiddle

Dacre Denny
  • 29,664
  • 5
  • 45
  • 65
0

It is not wise to mix AngularJS and jQuery this way.

The major problem with this approach is that $compile adds watchers to the specified scope. Those watchers will remain after added elements are removed from the DOM. This will result in memory leaks. If this is a dialog box that is constantly being added and removed -- beware.

But if you must, don't use innerHTML to append compiled content:

  ̶d̶o̶c̶u̶m̶e̶n̶t̶.̶g̶e̶t̶E̶l̶e̶m̶e̶n̶t̶B̶y̶I̶d̶(̶'̶d̶i̶a̶l̶o̶g̶b̶o̶x̶f̶o̶o̶t̶'̶)̶.̶i̶n̶n̶e̶r̶H̶T̶M̶L̶ ̶=̶ ̶c̶o̶n̶t̶e̶n̶t̶;̶
  var foot = document.getElementById('dialogboxfoot');
  $(foot).append(content);

The DEMO

angular.module("app",[])
.controller("ctrl",function($scope, $compile) {
  var html = $('<button ng-click = "cancelAlert()" > Cancel</button > <button ng-click="continueAlert()">Continue</button>');
  var div = $compile(html);
  var content = div($scope);
  document.getElementById('dialogboxhead').innerHTML = "header";
  document.getElementById('dialogboxbody').innerHTML = "body";
  var foot = document.getElementById('dialogboxfoot');
  $(foot).append(content);
})
<script src="//unpkg.com/jquery"></script>
<script src="//unpkg.com/angular/angular.js"></script>
<body ng-app="app" ng-controller="ctrl">
    <div id="dialogoverlay"></div>
    <div id="dialogbox">
        <div id="dialogboxhead"></div>
        <div id="dialogboxbody"></div>
        <div id="dialogboxfoot"></div>
    </div>
</body>
georgeawg
  • 48,608
  • 13
  • 72
  • 95