0

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/

2 Answers 2

3

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

Sign up to request clarification or add additional context in comments.

11 Comments

It is not working, it says $scope.new is not a function. I am in a factory function that has received $scope as a variable from the controller
I'm looking at it, I can see there the functions and variables defined in the controller so I guess it is injected. With the (true) it says the same.
The message is "Uncaught (in promise) TypeError: $scope.new is not a function(…)"
Yes, I've found it now in stackoverflow.com/questions/28307345/… , now then the message is the same as the answer above: TypeError: Failed to execute 'appendChild' on 'Node': parameter 1 is not of type 'Node'.(…)
The sentence document.getElementById('main_div').appendChild(run_div); works well, so this has to be discarded
|
1

You need to compile your run_div before insert it inside your DOM:

just use the $compile service this way:

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

you should consider using directives, though: manipulating the DOM inside your controller it's not advised.

Edit 1:

create a directive this way:

.directive('myShinyElement', function() {
  return {
    restrict: 'E',
    scope: {
      text: '='
    },
    template '<div class="whatever" ng-mouseover="mouseOver()">{{text}}</div>',
    link: function(scope, element, attrs, tabsCtrl) {
       scope.mouseOver = function(){
          console.log('mouseover');
       }
    }
  };
});

and use it in your html:

<my-shiny-element text="Dataset.analysis[$index].dataset.name"> </my-shiny-element>

7 Comments

It complains that what I am appending is not a Node, I guess it's the same error that I have with the answer below. However, I am not strictly speaking manipulating the DOM, I am creating the DOM and I'm using a factory. Where should I be doing this?
*Sorry, the "Dataset.ana..." was not meant to be there. In any case, in my case I need to add several elements (like 500), I don't think I should add dynamically them in the form my-shiny-element and then again dynamically to change the text, I believe it must be way more efficient to add the nodes already with the proper text.
But, the important thing here is that I cannot compile the node, throws the error mentioned in the first comment
try to change your document.createElement('div') to angular.element(document.createElement('div'));
Then it complains that setAttribute is not a function
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.