1

Consider the following webpage:

<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>First Test</title>
<script src="jquery-3.2.1.min.js"></script>
<script src="angular.js"></script>
<script>
    var myApp = angular.module('myApp',[]);
    function addDiv(){
    var div = "<script> \
        myApp.controller('myController', function ($scope) { \
            $scope.testDynamic = function(){ \
                alert('it works!'); \
            } \
        }); \
        <\/script> \
        <div ng-controller=\"testController\">{{\"TEST\"}}<button ng-click=\"testDynamic();\">Click Me!</button></div>";
        $("body").append(div);
        // How to use $compile here???
    }
</script>
<link href="bootstrap.css" rel="stylesheet" />
<link href="bootstrap-theme.css" rel="stylesheet" />
</head>
<body>
<div>{{"AngularJS"}}</div>
<button onclick="addDiv();">addDiv</button>
</body>
</html>

When the content is appended to the body, how I can load/compile the angularjs part? I have tried to use $compile like:

angular.element('body').injector().invoke(function ($compile, $rootScope) {
                            $rootScope.$apply(function() {
                                var scope = angular.element(div).scope();
                                $compile(div)(scope);
                            });
                        });

But without any success. I get the error: "Error: [ng:areq] Argument 'scope' is required..."

Someone can help?

3 Answers 3

2

After some tries, I got it working. It was simpler than I thought. After the definition of angular module, I need to add this configuration part:

myApp.config(['$controllerProvider','$compileProvider', '$filterProvider', '$provide', function($controllerProvider, $compileProvider, $filterProvider, $provide) {
    myApp.register = {
      controller: $controllerProvider.register,
      directive: $compileProvider.directive,
      filter: $filterProvider.register,
      factory: $provide.factory,
      service: $provide.service
    };

Then to register the controller coming from ajax:

myApp.register.controller('myController', function($scope) {
   $scope.name = "Pippo";
   $scope.age = 18;
   $scope.go = function(){alert('It works!')}
});

Then, at the success call from ajax add the compile part:

$compile($('#remdiv'))($scope);

Here's the complete code:

	<!DOCTYPE html>
    <html ng-app="myApp">
	<head>
	<title>First Test</title>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
    <script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.9/angular.min.js"></script>
	<script>
        myApp = angular.module('myApp',[])
		.controller("mainCtrl", function($scope, $http, $compile, $rootScope){
			$scope.addDiv = function(){
			var ajaxhtmlcode = '<script> \
				myApp.register.controller(\'testc\', function($scope) { \
					$scope.name="Pippo"; \
					$scope.age=18; \
					$scope.go = function(){alert(\'It works!\')} \
				}); \
				<\/script> \
				<div id="remdiv" ng-controller="testc"> \
				{{msg}} \
				Name:<input ng-model="name" /> \
				Age:<input ng-model="age" /> \
				<button ng-click="go();">Go!<\/button> \
				<\/div>';
			$('body').append(ajaxhtmlcode);	
			$compile($('#remdiv'))($scope);
			}
		});
		
		myApp.config(['$controllerProvider','$compileProvider', '$filterProvider', '$provide', function($controllerProvider, $compileProvider, $filterProvider, $provide) {
			myApp.register = {
			  controller: $controllerProvider.register,
			  directive: $compileProvider.directive,
			  filter: $filterProvider.register,
			  factory: $provide.factory,
			  service: $provide.service
			};
		}
		]);
    </script>
    </head>
    <body ng-controller="mainCtrl">
    <div>{{"AngularJS"}}</div>
    <button ng-click="addDiv();">addDiv</button>
    </body>
    </html>

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

Comments

0

1- First of all you have incorrect controller naming, you inject a controller named myController but you trying to call controller named testController

2- you can't declare new controller with this way you have to declare it first and inject the template only via compile method

<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>First Test</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<script>

    var myApp = angular.module('myApp',[])
    .controller("mainCtrl",function($compile,$scope,$rootScope){
    $scope.addDiv=function(){
    var div = $compile("<div ng-controller=\"test\">{{\"TEST\"}}<button ng-click=\"testDynamic();\">Click Me!</button></div>")($rootScope);
        $("body").append(div);
        // How to use $compile here???
    }
    
    })
    
       .controller('test', function ($scope) { 
            $scope.testDynamic = function(){ 
                alert('it works!'); 
            } 
        }); 
        
    
</script>
<link href="bootstrap.css" rel="stylesheet" />
<link href="bootstrap-theme.css" rel="stylesheet" />
</head>
<body ng-controller="mainCtrl">
<div>{{"AngularJS"}}</div>
<button ng-click="addDiv();">addDiv</button>
</body>
</html>

Comments

0

Thank you Peter. The first was a copy-paste mistake. I am new in Angular and I am just trying to understand how it works. Your solution works, but what I wanted to point our is this: What about if I can't define the controller "test" BEFORE? I mean, if the controller definition comes from a html ajax request (I mean if the div variable is populate by an ajax request, controller definition included). That's why I have put the script definition inside the div variable.

Taking back my example...main page:

<!DOCTYPE html>
<html ng-app="myApp">
<head>
<title>First Test</title>
<script src="jquery-3.2.1.min.js"></script>
<script src="angular.js"></script>
<script>
    var myApp = angular.module('myApp',[])
        .controller("mainCtrl",function($compile,$scope,$rootScope, $http){
            $scope.addDiv=function(){
            $http({
                url: "test.php",
                method: "post",
                data: '',
                responseType: 'text',
                headers: {
                  'Content-Type': 'application/x-www-form-urlencoded'
                }
            }).then(function successCallback(response) {
                    $('body').append(response.data);
                }, function errorCallback(response) {
                     alert(response.statusText);
            });
            }
        });
</script>
<link href="bootstrap.css" rel="stylesheet" />
<link href="bootstrap-theme.css" rel="stylesheet" />
</head>
<body>
<div ng-controller="mainCtrl">{{"AngularJS"}}
<button ng-click="addDiv();">addDiv</button>
</div>
</body>
</html>

Where test.php is simply:

<script>
myApp.controller('myController', function ($scope) {
            $scope.name = "Pippo";
            $scope.age = 10;
            });
</script>
<div ng-controller="myController">
Name:<input ng-model="name" />
Age:<input ng-model="age" />
</div>

If I run this code, I can't see the input (name and age) populated as defined in "myController"...

Comments

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.