0

<!DOCTYPE HTML>
<html lang="en-US" ng-app="theapp">
<head>
	<meta charset="UTF-8">
	<title>asd</title>
	<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
	<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
	<script type="text/javascript">
	var mainScope;
	angular.module('theapp', []).controller('MainCtrl', function($scope, $injector) {
	  $scope.demo = "test123";
	  $scope.scopecomp = function(){
		angular.element(document).injector().invoke(function ($compile) {
			$compile(document.body)($scope);
		});
	  }
	  mainScope = $scope;
	});
	function addDiv(){
		var $newDiv = $('<div>{{demo}}</div>');
		$(document.body).append($newDiv);
	}
	function comp(){
		mainScope.comp();
	}
	</script>
</head>
	<body ng-controller="MainCtrl" ng-change="comp();">
		<h1>{{demo}}</h1>
		<input type="text" id="compText" />
		<button onclick="addDiv();">add</button>
		<button ng-click="scopecomp();">compile with ng-click (works fine)</button>
		<button onclick="comp();">compile with onlick (not working)</button>
	</body>
</html>

I want to run the comp() function anywhere in my project. I tried button onclick,it didn't work but ng-click works fine. What is the problem ? Why onclick doesn't work ?


New : changeContent function added.

<!DOCTYPE HTML>
<html lang="en-US" ng-app="theapp">
	<head ng-controller="MainCtrl as main">
		<meta charset="UTF-8">
		<title>asd</title>
		<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"></script>
		<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.5.8/angular.min.js"></script>
		<script type="text/javascript">
		angular.module("theapp", []).controller("MainCtrl", MainController);
		MainController.$injector = ['$timeout'];
		var vm;
		function MainController($timeout) {
			vm = this;
			vm.post = null;
			function loadStuff(){
				$timeout(function() {
					vm.post = {
						title: "Post Title",
						content: "Post Content"
					};
				}, 1000);
			}
			loadStuff();
			
		}
		function changeContent(){
			vm.post.content = "<div>new content </div>";
		}
		</script>
	</head>
	<body ng-controller="MainCtrl as main">
		<p ng-hide="main.post">Loading...</p>
		<h3>{{main.post.title}}</h3>
		<p>{{main.post.content}}</p>
		<button onclick="changeContent();">change</button>
	</body>
</html>

New bodyController()

function bodyController($scope, $injector) {
	_bodyController = this;
	$scope.title = "ttt";
	$scope.content = "aaa";
	$scope.comp = function(){
		angular.element(document).injector().invoke(function ($compile) {
			$compile(document.body)($scope);
		});
	}
	myAPP.Run(function(){
		$scope.title = globalOBJ.title;
		$scope.content = globalOBJ.content;
		$scope.comp();
	});
}

2 Answers 2

1

You should change your '' to this:

<body ng-controller="MainCtrl" ng-model="demo" ng-change="comp();">

If you check the url from the first line of the error log: https://docs.angularjs.org/error/$compile/ctreq?p0=ngModel&p1=ngChange. The problem is explained:

Controller 'ngModel', required by directive 'ngChange', can't be found! Description This error occurs when HTML compiler tries to process a directive that specifies the require option in a directive definition, but the required directive controller is not present on the current DOM element (or its ancestor element, if ^ was specified).

To resolve this error ensure that there is no typo in the required controller name and that the required directive controller is present on the current element.

The directive 'ng-change' require a 'ng-model' to work properly, that is why you are getting an compile error.

Now your second question, "Why onclick doesn't work ?". You should never manipulate the DOM from the controller, if you have to do that use a directive. When you call "scopecomp()" from the ng-click that method is invoked from "within" the angular engine, it will fire an digest cycle which will process the "html" (it's more than that, I'm trying to keep it simple) and print what you expect, but when you add "{{demo}}" directly to the DOM, that variable will not be processed.

There is no need to change the DOM manually to do what you are looking for, check the snippet below. I simulated your "database request" with a timeout function.

angular.module("app", [])
      .controller("MainController", MainController);

MainController.$injector = ['$timeout'];
function MainController($timeout) {
  var vm = this;
  vm.post = null;
    
  function loadStuff() {
    $timeout(function() {
      vm.post = {
        title: "Post Title",
        content: "Post Content"
      };
    }, 1000);
  }
  loadStuff();
  
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>

<div ng-app="app" ng-controller="MainController as main">
  <p ng-hide="main.post">Loading...</p>
  <h3>{{main.post.title}}</h3>
  <p>{{main.post.content}}</p>
</div>

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

13 Comments

can you give me an example : I want to recompile body when it is changed ?
What exactly are you trying to accomplish? Maybe there is a better way
I'm making a project which uses database. After documents load, I have to wait when database requests are responsed. If it respose, i will get a json data like {title:"mytitle",content:"post content"}. Then, the scope gets this data and calls post.html (the body element in this file. For example, if data type is page, my function calls page.html) If all complete, I have to compile the called html file.
Checkout the snippet I added to the question, there is no need to change da DOM manually to accomplish what you are looking for (if I got it right)
Thank you for your documents but the project is realtime. I have to recompile body element. How can do that (I gave you +1)
|
0

$FirebaseJS.Run(function(){
		$scope.$apply(function(){
			$scope.obj = globalOBJ;
		});
	});

Finally I got it.

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.