Search code examples
javascriptangularjsdom-eventsonmouseover

Javascript, angularjs, can a ng-mouseover be inserted dynamically?


This code doesn't apparently work:

var run_div = document.createElement('div');
run_div.className = 'whatever';
run_div.textContent = 'whatever';
run_div.setAttribute('ng-mouseover', 'console.log(\'ei\')');
document.getElementById('main_div').appendChild(run_div);

I guess it is because ng-mouseover has to be there from the beginning so that AngularJS knows (?). Is this the case? Is there any way to do this?


(below: UPDATE 1, UPDATE 2, UPDATE 3)

UPDATE 1:
This code works in a factory, where from the controller I call the factory method sending it the $scope:

angular.module('whatever').controller('mycontroller', 
['$scope', '$q', '$window', '$timeout',
function ($scope, $q, $window, $timeout) {

$scope.myfunction= function() {
  myfactory.mymethod($scope);
};

And the factory calls the $compile in its definition:

angular.module('whatever').factory('myfactory', 
['$window', '$q', '$compile',
function($window, $q, $compile) {

...

mymethod = function($scope) {
    var run_div = document.createElement('div');
    run_div.className = 'whatever';
    run_div.textContent = 'whatever';
    run_div.setAttribute('ng-mouseover', 'console.log(\'ei\')');
    document.getElementById('main_div').appendChild(run_div);
}

Which doesn't work, and then this throws an error:

document.getElementById('main_div').appendChild($compile(run_div)($scope));
document.getElementById('main_div').appendChild($compile(run_div)($scope.new()));

or even:

var run_div = angular.element(document.createElement('div'));
run_div.addClass('whatever');
run_div.attr('ng-mouseenter', 'console.log(\'ei\'');
document.getElementById('main_div').appendChild($compile(run_div)($scope));

where it complains that when appending, the parameter is not a node.

Uncaught (in promise) TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.(…)


UPDATE 2:

The following code shows (I think) that when compiling and appending from a factory it doesn't work, but when doing it from a controller, it works (see answer 2):

http://jsfiddle.net/xsaudasp/1/


UPDATE 3

I can see that this has to work, as shown here:

http://jsfiddle.net/2uk2qe92/4/


Solution

  • First you need to create new $scope instance for your directive and then use $compile service to compile given div with that scope:

    var directiveScope = $scope.$new();
    var compiledDirective = $compile(run_div)(directiveScope);
    

    Then you can append it to DOM:

    angular.element('#my_dir').append(compiledDriective);
    

    You must ensure that jQuery is loaded before angular so the jQuery selectors are availible. If you don't want to use jQuery you can use jqLite selector instead:

    angular.element(document.querySelector('#my_dir')).append(compiledDirective)
    

    Here is working jsfiddle of what you need: jsfiddle