Reputation: 390
<!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 ?
<!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();
});
}
Upvotes: 0
Views: 710
Reputation: 390
$FirebaseJS.Run(function(){
$scope.$apply(function(){
$scope.obj = globalOBJ;
});
});
Finally I got it.
Upvotes: 0
Reputation: 2748
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>
Upvotes: 1