Because of the following quote in this thread
The best practice is never use JQuery or angular.element() for DOM manipulation inside controllers. Controllers are only used for our business logic.
I have moved a big function that calls CodeMirror and JQuery outside a controller. The big function is used to combine the content of two textareas. JSBin
Html:
<div ng-app="myApp" ng-controller="myCtrl">
<textarea ng-model="area1">area1</textarea>
<textarea ng-model="area2">area2</textarea>
<div>First: {{area1}}, {{area2}}</div>
<div id="output"></div>
<script>
function bigfunction(area1, area2) {
// a big function, the following is for the sake of simplicity
return "Second: " + area1 + ", " + area2
}
var output = bigfunction({{area1}}, {{area2}});
$("#output").html(output)
</script>
</div>
Javascript:
var app = angular.module('myApp', []);
app.controller('myCtrl', function($scope) {
$scope.area1 = "initial textarea1";
$scope.area2 = "initial textarea2"
});
Does anyone know why {{area1}} and {{area2}} in the script are not recognised?
The problem is that you're mixing JavaScript with AngularJS templates.
var output = bigfunction({{area1}}, {{area2}});
You cannot expect inline JavaScript to work using AngularJS templates. Here's what happens: the HTML file (template) is loaded and the inline JS is parsed and executed. It fails because it contains erroneous syntax ({{area1}}). This occurs before AngularJS is even loaded. Also, JavaScript code is evaluated but once, so even if the template actually replaced the {{area1}} with a string, the code would not be reevaluated and would not produce a different output. You will need to change your approach entirely.
I'm guessing that you would like to perform the joining of the two scope variables outside the controller and perhaps add extra logic to that. You can either move the code to a service and then use it in your controller, or use a directive (I don't know your exact use case, so it's hard for me to say which approach will make more sense).
Since what you described is simple concatenation of two model values, a directive appears to make sense. Your HTML could look like this:
<div ng-app="myApp" ng-controller="myCtrl">
<textarea ng-model="area1">area1</textarea>
<textarea ng-model="area2">area2</textarea>
<div>First: {{area1}}, {{area2}}</div>
<output area1="area1" area2="area2"></output>
</div>
And in the JS, add this simple directive:
app.directive('output', function() {
return {
restrict: 'E',
template: '<div id="output">Second: {{area1}}, {{area2}}</div>',
scope: {
area1: "=",
area2: "="
}
};
});
If for some reason you wish to add extra logic to your directive, you can always do that in the linking function.
Were you to add a service, the HTML would again require only a minor change:
<div ng-app="myApp" ng-controller="myCtrl">
<textarea ng-model="area1">area1</textarea>
<textarea ng-model="area2">area2</textarea>
<div>First: {{area1}}, {{area2}}</div>
<div>{{output}}</div>
</div>
And the JS could look like this:
app.controller('myCtrl', function($scope, joiner) {
$scope.area1 = "initial textarea1";
$scope.area2 = "initial textarea2";
$scope.$watchGroup(["area1", "area2"], function() {
$scope.output = joiner.join($scope.area1, $scope.area2);
});
});
app.service('joiner', function() {
this.join = function(a1, a2) {
return "Second: " + a1 + ", " + a2;
};
});
The service can contain any logic you need.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With