Can I have Angular ng-href bind variables within a string - angularjs

I'd like to bind a links href property to a variable in my controller but I'd also like to have that url be bound to variables. I'd like to accomplish this using the built in binding and without having to manually watch for changes and reload the url. Is this possible?
// In the controller
$scope.section = 'section1';
$scope.page = 'page1';
$scope.url = 'http://myurl/{{section}}/{{page}}';
<!-- In the template -->
<a ng-href="{{url}}">Page Link</a>
This is a simplification of my actual code. Declaring the url pattern in the template would work but I need to have the url be defined in a string that gets passed in.

Just set the ng-href
<a ng-href="http://myurl/{{section}}/{{page}}">Page Link</a>

In the controller, you don't need to use curly braces expressions.
Replace this:
$scope.url = 'http://myurl/{{section}}/{{page}}';
With this:
$scope.url = 'http://myurl/'+$scope.section+'/'+$scope.page;
And to bind it in your template, use:
<a ng-href="http://myurl/{{section}}/{{page}}">Page Link</a>
So, you can now watch for any changes.

Related

Set Default Value to ng-bind in HTML

I'd like to set a default value to scope, which is picked up by ng-bind. I am doing this like:
<button>Show <span data-ng-bind="data.text" data-ng-init="data.text = 'All';"></span> Names</button>
In this example, the span is set to innerHTML = 'All' when the page loads.
However, I was hoping there might be a way to do this without requiring the use of ng-init, maybe something like:
<button>Show <span data-ng-bind="data.text = 'All';"></span> Names</button>
In your controller:
$scope.data = {};
$scope.data.text = "All";
Your markup:
<button>Show <span data-ng-bind="data.text"></span> Names</button>
Or, if you want to skip the controller code (courtesy of Kohjah Breese' comment):
<button>Show <span data-ng-bind="data.text || 'All'"></span> Names</button>
Presumably there will be some code elsewhere in your controller that will toggle this value, but for the purposes of initializing, that should do.
EDIT: Alternately, as tymeJV points out in the comments (ng-cloak added so {{}} syntax doesn't display to users):
<button>Show <span ng-cloak>{{data.text || "All"}}</span> Names</button>
The || operator works also in ngBind like in pure JavaScript:
<span ng-bind="myVariable || 'My default value'"></span>
This outputs myVariable if the variable is filled, otherwise the alternative 'My default value' is used.
from angularjs doc :
The only appropriate use of ngInit is for aliasing special properties of ngRepeat [...] Besides this case, you should use controllers rather than ngInit to initialize values on a scope.
So i guess initializing data.text in your controller is fine for angularjs

ng-bind-html strips elements attributes

I'm trying to interpolate a string that contains some markup in a template.
In the controller:
$scope.message = "Hello moto <a ui-sref='home.test'>click</a>";
Template:
<div ng-bind-html="message.text"></div>
which renders as:
<div ng-bind-html="message.text" <div="" class="ng-binding">Hello moto <a>click</a></div>
Trying to use the following filter does not help either; the text is simpy escaped for either of the commented choices:
angular.module('test-filters', ['ngSanitize'])
.filter('safe', function($sce) {
return function(val) {
return $sce.trustAsHtml(val);
//return $sce.trustAsUrl(val);
//return $sce.trustAsResourceUrl(val);
};
});
How can I interpolate my string without escaping it nor stripping attributes?
Edit: Plunker http://plnkr.co/edit/H4O16KgS0mWtpGRvW1Es?p=preview (updated with sylwester's version that has reference to ngSanitize
Let have a look here http://jsbin.com/faxopipe/1/edit it is sorted now.
It didn't work because there was another directive inside a tag 'ui-sref',
so you have to use $sce service.
in your js please add method:
$scope.to_trusted = function(html_code) {
return $sce.trustAsHtml(html_code);
and in view :
<p ng-bind-html="to_trusted(message)"></p>
In scenario where you are using ui.router path you must need to use $compile in combination with $sce for your dynamic html so that ui-sref work properly. If you don't do that you'll just see a Link which actually do not work.
e.g <span> Hello moto <a ui-sref='home.test'> Link </a> </span>
//You must need to add boundary conditions, this is just for demonstration
$scope.to_trusted = function(someHTML) {
var compiledVal = $compile(someHTML)($scope);
var compiledHTML = compiledVal[0].outerHTML;
return $sce.trustAsHtml(compiledHTML);
}
And you use like this,
<p ng-bind-html="to_trusted(message)"></p>
Note that your message has to be a valid HTML starting from "<" so if you pass a non HTML to $compile you'll get jqlite error. I used <span> to handle your case.
You missed reference to angular-sanitize.js and you have inject it as well to angular.app
var app = angular.module('plunker', ['ngSanitize']);
the simplest option in to bind html is ng-bind-html :
<li>link ng-html-bind <div ng-bind-html="message"></div></li>
please see Plunkr

Rendering dynamic HTML(angularjs content) content after ajax call in AngularJS

I am new to Angular getting stuck after making ajax call. How do I render/compile the html content once you inject in DOM so that I can still use the AngularJs functions.
Due to the way my backend is set up I have to get content via ajax ($http). And I am making the app without jQuery. I tried $compile and $apply but didn't work. What am I missing here.
I have the code set up at http://jsfiddle.net/rexonms/RB7FQ/3/ . I want the second div content to have the same properties as the first div.
HTML
<div ng-controller="MyCtrl" class="section">
<input ng-model="contentA">
<div>
And the input is: {{contentA}}
</div>
</div>
<div ng-controller="MyAjax" class="section">
<div id="dumpAjax">
{{ajaxData}}
</div>
<button ng-click=getajax()> Get Ajax</button>
</div>
SCRIPT
var myApp = angular.module('myApp',[]);
//myApp.directive('myDirective', function() {});
//myApp.factory('myService', function() {});
function MyCtrl($scope) {
}
function MyAjax($scope){
var data = '<input ng-model="contentB">{{contentB}}';
$scope.getajax = function(){
$scope.ajaxData = data;
}
}
Thanks in advance.
ng-bind-html-unsafe is not available 1.2 and later verison of angular...
so you should use ng-bind-html which creates a binding that will innerHTML the result of evaluating the expression into the current element in a secure way.
using $scope variable in your string make it unsafe, so you should use $sce.trustAsHtml but this time variables in your string cannot be bind because they will be not compiled...
basically you should compile your string in order to bind your variables. Here comes custom directives you can create a directive which can replace with ng-html-bind...
Writing a custom directive which extends ng-bind-html with some extra functions can be a solution...
here is my PLUNKER
and here is your updated JSFIDDLE with my solution...
Instead of {{ajaxData}}, you should use something like:
<div ng-bind-html-unsafe="ajaxData"></div>
However, you'd still need to set the proper model to bind the contentB and get it working.

Dynamic variable name directive attribute

I have a my-edit directive that has a value attribute expecting a scope variable to bind to.
<my-edit value="myVar"></my-edit>
is there any way to do something like this:
<my-edit value="{{varName}}"></my-edit>
where varName = "myVar"
I want to nest this directive in "my-listbox" directive that has a "text-field" attribute
<my-listbox ng-model="myList" text-field="itemProp"></my-listbox>
So I was trying use a template like:
<div>
<ul>
<li ng-repeat="item in items">
<my-edit value="item.{{textField}}"></my-edit>
</li>
</ul>
</div>
But obviously it doesn't work
I guess using a text binding is also not the solution.
Is a dynamic generated template for "my-listbox" the way to go here?
I tried that in the compile function but the didn't work that well because of the nested neRepeat directive. Should it by done using $compile in link function?
Thanks
This is something pretty cool about angular, it evaluated the string that you pass to the directive. This means that you can actually just do value="item[textField]" and that will work.
For instance if you had a controller with data like this:
$scope.data = {
test: 'test_val',
other: 'other_val'
};
$scope.val = 'test';
You could just pass it like this to your directive:
<directive value="data[val]"></directive>
That is set up like this:
scope: {
value: '='
},
And the isolate scope will have scope.value = 'test_val' and will update to 'other_val' just by changing the original controller val to 'other'
I made a fiddle where this is set up for you to play with.
Hope this helps!

Replacing ng-href with ng-click

I am developing a mobile application and found that angularjs 1.1.4 has a ngTap directive available replacing standard ng-click. It makes app more robust, so I've decided to replace all my ng-href directive with ng-tap. For this purpose I've created a "go()" function available from $rootScope. The problem is that it can not resolve the url variable.
Here's my code.
$rootScope.go = function (url) {
$location.path(url);
}
and in template:
<a class="niceButtonLikeStyled" data-ng-click="go(/somewhere/var.id/)">{{ var.id }}</a>
Using data-ng-click as ngTap is portable and replaces ng-click if new ngMobile loaded.
My problem seems to be with go() argument (mixing static & variable content ?
Maybe there's the other way of just binding new ng-click to all links.. or simply adding own directive that would take value from ng-href and made the location redirect and attach the ng-tap click event.
AngularJS Expressions for ng-click
When you use ng-click, you're calling an AngularJS expression.
Your current code's expression is this:
go(/somewhere/var.id/)
You need to quote that string:
go('/somewhere/' + var.id + '/')
Other Issues
Another issue with your code: The function go should be in the scope of the controller rather than in the $rootScope:
angular.module('MyModule').controller(
'MyController',
function ($scope, $location) {
$scope.go = function (url) {
$location.path(url);
}
}
);
Here's how your template would look:
<div ng-controller="MyController as mycontroller">
<a class="niceButtonLikeStyled"
data-ng-click="mycontroller.go('/somewhere/' + var.id + '/')">
{{ var.id }}
</a>
</div>
That's the biggest issue with the code, you're using $rootScope instead of putting the variables and functions you need in the scope of a controller where it belongs.

Resources