Angularjs: Html render as text - javascript

I have an Angularjs script to create a navigation Bar using users parameters.
The problem is that, when i try to render the html structure, it always displays as plain text
This is the script:
var app = angular.module('userData', []);
app.controller('showUserData', ['$scope', function($scope){
$scope.userPar = JSON.parse(sessionStorage.userPar);
$scope.navBar = createNavBar($scope.userPar);
$scope.logOut = function(){
alert('Out you go!');
}
}]);
app.directive("otcNavbar", function(){
return {
template:"{{navBar}}"
};
});
function createNavBar(userPar){
var navBar = "<ul id=\"nav\">";
if(userPar.isDir == 1){
navBar +=
"<li class=\"seccion\">Director</li>";
}
if(userPar.isSys == 1){
navBar +=
"<li class=\"seccion\">System</li>";
}
navBar +=
"<li class=\"seccion\">Log Out</li></ul>";
return navBar;
}
This is the template:
<html>
<head>
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link id="css" rel="stylesheet" href="main.css" type="text/css" />
<script src="angular.min.js"></script>
<script src="mainApp.js"></script>
</head>
<body>
<div id="userPar" ng-app="userData" ng-controller="showUserData">
<table id="sessionData">'.
<tr><th colspan="6">User Data</th></tr>'.
<tr><td class="R B">User No.:</td><td class="L">{{userPar.suID}}</td>.
<td class="R B">Name:</td><td class="L">{{userPar.sulName}}, {{userPar.sufName}}</td>.
<td class="R B">Access:</td><td class="L">{{userPar.utName}}</td></tr>
</table>
<!--<div id="navBar" otc-navbar></div>-->
<div id="navBar" ng-bind="navBar"></div>
</div>
</body>
</html>
I tried a directive (otc-navbar) and ng-bind, but in both cases i get plain text instead of html.
How can I make it work? Thanks in advance!

Use ng-bind-html with angular sanitize
<div id="navBar" ng-bind-html="navBar"></div>
ng-bind-html will evaluates your expression and inserts the resulting HTML into the element. By default, the resulting HTML content will be sanitized using the $sanitize service. In order to use ngSanitize, you need to include "angular-sanitize.js" in your application.
So include angular-sanitize.js in your page and inject the dependency to your angular module.
var app= angular.module('userData', ['ngSanitize']);
Here is a working sample on jsbin. :)
EDIT : As per the comment you wish ng-sanitize to not strip out the html attributes.
By default, ng-sanitize strips certain attributes out. If you really want that to not happen, You can use the $sce service's trustAsHtml method to explicitly tell angular that the markup you are passing is safe.
Here is a working sample

Related

Calling an AngularJS controller function from outside of it

I have the following code:
app.controller('MatrixExpertCtrl', function($scope,$http){
$scope.PassedMatrix=[];
$scope.GetMatrixFromServer=function(){
$http.get("http://localhost:3000/getmatrixfromdb").success(function(resp){
alert("The matrix grabbed from the server is: " + resp[0].ans);
$scope.PassedMatrix.push(resp[0].ans);
});
};
$scope.DispSize=function(){
alert("testing");
alert("The size is "+$scope.PassedMatrix[0].size) ;
};
//$scope.GetMatrixFromServer();
});
Now, suppose, in HTML, I have something like this:
<div class="col-sm-3 col-md-3 col-lg-3">
<div class="text-center">
<h3>Example Survey</h3>
<p>example paragrah</p>
<p>More random text</p>
<p>ending the paragraphs</p>
<button id="updmat" ng-click="DispSize();" type="button" class="btn btn-default">Updates</button>
</div>
//Much more code
<div id="body2">
<div class="col-sm-6 col-md-6 col-lg-6" style="background-color:#ecf0f1;">
<div ng-controller="MatrixExpertCtrl" ng-app="app" data-ng-init="GetMatrixFromServer()">
<div class="text-center">
Meaning with this:
Is it possible to call a function that is defined inside a controller, from outside of the scope of that same controller?
I need this because the function is manipulating a shared object, owned by the controller in a very very simple fashion (for example, clicking on the button changes the color of a given element).
I am having trouble to make this work, any help will be appreciated.
I think that declaring some data structures as global would help me solving this problem, but, I would like to avoid doing that because, besides it being bad practice, it might bring me more problems in the future.
If i understand your problem correctly than what you basically do have is one utility function which will work on your shared object and do your useful things (i.e. clicking on the button changes the color of a given element) and now you do require the same behaviour in another controller outside of it's scope. You can achieve the same thing in 2 different ways :
1).Create a service and make it available in your controllers like this :
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
<script type="text/javascript">
var myApp = angular.module('myApp', []);
myApp.factory('myService', function() {
return {
changeColour: function() {
alert("Changing the colour to green!");
}
};
});
myApp.controller('MainCtrl', ['$scope', 'myService', function($scope,
myService) {
$scope.callChangeColour = function() {
myService.changeColour();
}
}]);
</script>
</head>
<body ng-controller="MainCtrl">
<button ng-click="callChangeColour()">Call ChangeColour</button>
</body>
</html>
Pros&Cons: More angularistic way, but overhead to add dependency in every different controllers and adding methods accordingly.
2).Access it via rootscope
<!doctype html>
<html ng-app="myApp">
<head>
<script src="http://code.jquery.com/jquery-1.9.1.min.js"></script>
<script src="http://code.angularjs.org/1.1.2/angular.min.js"></script>
<script type="text/javascript">
var myApp = angular.module('myApp', []);
myApp.run(function($rootScope) {
$rootScope.globalChangeColour = function() {
alert("Changing the colour to green!");
};
});
myApp.controller('MainCtrl', ['$scope', function($scope){
}]);
</script>
</head>
<body ng-controller="MainCtrl">
<button ng-click="globalChangeColour()">Call global changing colour</button>
</body>
</html>
Pros&Cons: In this way, all of your templates can call your method without having to pass it to the template from the controller. polluting Root scope if there are lots of such methods.
try removing semicolon
ng-click="DispSize()"
because it binds ng-click directive to the function.

adding ngAnimate to controller makes app to not displaying content

I'm trying to add animation when changing the content inside a my html using ng-inculde, but when ever i add ['ngAnimate'] in the declaration of the controller all of the content inside the main tag simply dissapear.
HTML:
<div ng-app="myApp">
<div ng-controller="firstCtrl">
<div id="wrapper">
<main ng-init="nav('data/table.html')">
<div ng-include="filePath">
</div>
</main>
</div>
</div>
</div>
JS:
var myApp = angular.module("myApp",['ngAnimate']);
myApp.controller ('firstCtrl', function($scope, PersonService){
$scope.users = PersonService.list();
$scope.saveUser = function () {
PersonService.save($scope.newuser);
$scope.newuser = {};
}
$scope.nav = function(path){
$scope.filePath = path;
}
})
this code wont work since im adding ['ngAnimate'] but if i'll delete it and keep the brackets empty the content will display. can someone tell me why and if its the correct way to get the animation when the content changes (table.html changes to a different file)
this is the header part incase needed:
<head lang="en">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<script src="http://maxcdn.bootstrapcdn.com/bootstrap/3.2.0/js/bootstrap.min.js"></script>
<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.12/angular-sanitize.js"></script>
<script src="https://code.angularjs.org/1.2.6/angular-animate.js"></script>
<script src="js/angular.min.js"></script>
</head>
Give reference of angular-animate.min.js file in order to use 'ngAnimate' module. You have to give reference of this file after angular.min.js.

Adding Config/RouteProvider breaks ng-repeat

This issue is most likely due to my naivity as I am just beginning to teach myself JS and AngularJS in parallel. I have put together a simple example of what I am seeing in this plunker. Basically, my app handles an ng-repeat correctly, but as soon as I add the config method it does not replace {{menuItem.itemName}} with the value of the variable. Now, my config method is currently empty, so that may be the problem. But, I assumed I could just have a no-op method and add routes as I went, testing each one.
Here is my HTML:
<html ng-app="site">
<head>
<script src = https://ajax.googleapis.com/ajax/libs/angularjs/1.3.0-beta.5/angular.min.js></script>
<script src ="script.js"></script>
<link href="http://fonts.googleapis.com/css?family=Great+Vibes" rel="stylesheet" type="text/css">
<title>Site</title>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
</head>
<body ng-controller='mainCtrl'>
<div id="main-container">
<div id="header">Site
</div>
<div id="side-bar">
<ul id="side-bar-menu">
<li ng-repeat="menuItem in menuItems"><span class="underline"><a ng-href={{menuItem.itemLink}}>{{menuItem.itemName}}</a></span></li>
</ul>
</div>
</div>
</body>
</html>
JS:
'use strict';
angular.module('site',[]).
controller('mainCtrl', ['$scope', function($scope) {
$scope.menuItems = [{
itemName: "Home",
itemLink: "#Home"
}];
}]);
//enabling the config breaks the output (and of course ;
//above needs to be replaced with . when config enabled)
/*config(['$routeProvider', function($routeProvider) {}]);*/

Apply in progress in Angular.JS

I have angularjs application and <span> in it. I try to hide it with ng-hide directive, but:
<span ng-hide="hideSpan">
And
// controller code here
....
$scope.hideSpan = true;
....
Doesn't work, it's ignoring. And if i make:
// controller code here
....
$scope.$apply(function(){$scope.hideSpan = true});
....
I get error: $apply already in progress.
How can i correctly use ng-hide/ng-show in this way?
Thank you.
You should be able to directly control the hide/show functions from your controller just as you show. The following is working example using a button to trigger toggling of hide show.
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#1.1.5" data-semver="1.1.5" src="http://code.angularjs.org/1.1.5/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="myapp" ng-controller="mycontroller">
<span ng-hide="hideSpan">Some Content to hide</span>
<button ng-click="toggleHide()"/>Toggle Hide</button>
</body>
</html>
And the script.
angular.module('myapp', []).controller('mycontroller', function($scope){
$scope.hideSpan = true;
$scope.toggleHide = function(){
if($scope.hideSpan === true){
$scope.hideSpan = false;
}
else{
$scope.hideSpan = true;
}
}
});
I've created a simple plunker to show this in action at http://plnkr.co/edit/50SYs0Nys7TWmJS2hUBt?p=preview.
As far as why the $apply is causing an error, this is to be expected as direct scope (provided by the $scopeProvider) variable operations are already watching for change and wrapped into a default apply of sorts in core angular so any change will be automatically applied to the other bindings of that variable.
you can just change the hideSpan value in ng-click, save few lines. cheers
<!DOCTYPE html>
<html>
<head>
<script data-require="angular.js#1.1.5" data-semver="1.1.5" src="http://code.angularjs.org/1.1.5/angular.min.js"></script>
<link rel="stylesheet" href="style.css" />
<script src="script.js"></script>
</head>
<body ng-app="myapp" ng-controller="mycontroller">
<span ng-hide="hideSpan">Some Content to hide</span>
<button ng-click="hideSpan=!hideSpan"/>Toggle Hide</button>
</body>

AngularJS with Closure Compiler - Simple Optimizations Fail

Can someone please shed light on why simple optimizations are failing for me in AngularJS? More importantly, how can I get them to work? (best practice/clarification for defining controllers is welcome too).
Here's my scenario, greatly simplified.
I'm using this HTML:
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html ng-app="">
<head>
<link href="http://ajax.googleapis.com/ajax/libs/jqueryui/1/themes/excite-bike/jquery-ui.css" type="text/css" rel="stylesheet" />
<script src="http://ajax.googleapis.com/ajax/libs/angularjs/1.0.4/angular.min.js" type="text/javascript"></script>
<script src="simple_script.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jquery/1/jquery.min.js" type="text/javascript"></script>
<script src="http://ajax.googleapis.com/ajax/libs/jqueryui/1/jquery-ui.min.js" type="text/javascript"></script>
<script>
//inline JS here
$(function() {
var spinner = $( "#qtySpinner" ).spinner({
spin: function( event, ui ) {
scope.qty = ui.value;
scope.$digest();
//console.log( event );
}
}); //end spinner
var scope = angular.element(spinner).scope();
});
</script>
<title>Angular Testing</title>
</head>
<body>
<div ng-controller="InvoiceCntl">
<b>Invoice:</b><br>
<br>
<table>
<tr>
<td>
Quantity
</td>
<td>
Cost
</td>
</tr>
<tr>
<td>
<input id="qtySpinner" type="integer" min="0" ng-model="qty" required="">
</td>
<td>
<input type="number" ng-model="cost" required="">
</td>
</tr>
</table>
<hr>
<b>Total:</b> {{calculate(qty,cost)}}
</div>
<br>
</body>
</html>
And I'm using this highly minification proof (I thought) JS file as "simple_script.js", which actually works as is:
//this works
window["InvoiceCntl"] = function ($scope) {
$scope["qty"] = 1;
$scope["cost"] = 19.95;
$scope["calculate"] = function (xval, yval) {
return xval * yval;
};
}
Minified using Google Closure Compiler (http://closure-compiler.appspot.com/home) with SIMPLE_OPTIMIZATIONS, I get this, which breaks:
//this breaks, seemingly because "a" replaces "$scope"?
window.InvoiceCntl=function(a){a.qty=1;a.cost=19.95;a.calculate=function(a,b){return a*b}};
I presume it's because $scope is a key word Angular looks for (Dependency Injection?), because when I add the extra step, manually, of passing $scope and assigning it to a in the first line of the function, it works. Like so:
//manually passing "$scope" and immediately assigning it to "a" works
window.InvoiceCntl=function($scope){var a=$scope;a.qty=1;a.cost=19.95;a.calculate=function(a,b){return a*b}};
Why doesn't $scope behave like a normal function parameter in this situation?
Is there a way to minify (simple or advanced) angular code using Closure compiler (or something else) without a manual step like this?
Is $scope configurable or is it a fixed key word, i.e., could I changed the key word to "$myscope" when I'm defining the controller? (not sure that helps me anyway)
Thanks.
You should read http://docs.angularjs.org/tutorial/step_05
I think your concern about injecting '$scope' is correct.
You can inject like following.
var module = angular.module('youApp', []);
module.controller('yourCtrl', ['$scope', function($scope) {
$scope["something"] = "somevalue";
})];
Edit: The minification renames $scope, you can prevent this by adding:
InvoiceCntl.$inject = ['$scope'];

Categories