I have a ng-repeat for descriptions that have tags. I use init to filter the tags to rewrite the description with ng-click. However the ng-click doesn't work after. Is this possible?
<div ng-repeat="desc in descs">
<div ng-init="desc.description = getTags(desc.description )">
{{ desc.description }}
</div>
</div>
<script>
$scope.getTags = function(desc) {
var desc = desc.replace("#tag", '<span ng-click="function">#tag</span>');
return desc;
}
</script>
Thanks
Injected HTML code into AngularJS shall be processed with $compile
See official doc here : https://docs.angularjs.org/api/ng/service/$compile
You need to use ng-bind-html but you also need to create one filter that will sanitize that html using $sce service trustAsHtml method.
Markup
<div ng-repeat="desc in descs">
<div ng-bind-html="getTags(desc.description) | trustHtml">
</div>
</div>
Filter
app.filter('trustHtml', function($sce) {
return function(text) {
$sce.trustAsHtml(text);
};
}
Related
Tried to read about $compile, $parse and $eval however cannot get understand how to store a template in a variable then use it during rendering processes.
What I would like to achieve:
code:
const data = {
template: 'test {{foo}} some text {{bar}}',
}
html:
<p> some text </p>
<h1> <included in here: data.template> </h1>
result:
<p> some text </p>
<h1> test ... some text ... </h1>
Any ideas how to achieve this ?
By simple way you can create an html file for your template and use ng-include directive, so ng-include directive will the thing for you out of the box
my-template.html
<div>
<p> some text </p>
<h1> <included in here: data.template> </h1>
</div>
Or you can also create an ng-template on html page itself like shown below
<script type="text/ng-template" id="my-template.html">
<div>
<p> some text </p>
<h1> <included in here: data.template> </h1>
</div>
</script>
Usage:
Your consumer page
<ng-include
src="'my-template.html'">
</ng-include>
I understand by this solution you can end up creating multiple template html file or script templates. So other way around to solve this problem you can create your own directive and compile the content manually and render it inside a DOM manually.
Directive
.directive("dynamicContent", function($compile, $parse){
return{
link: function(scope, element, attrs) {
var linkFn = $parse(attrs.template);
var content = linkFn(scope)
// creating template wrapper around
var wrapper = `<div>${content}</div>`
var tempate = $compile(wrapper)(scope)
element.append(tempate);
}
}
});
Demo Plunker
Hej, how do I show only the first number that evaluates to true inside ng-repeat?
In my directive (or controller) I have:
ctrl.things = [1,2,3,4,5,6];
and in my html:
<div ng-repeat='thing in ctrl.things' >
<span ng-if="thing>3" ng-show="$first">{{thing}}</span>
</div>
How do I display only 4 as a result?
Please bear in mind that this example is simplified. There is actually an ng-repeat inside ng-repeat and because of that (and other things) there are not many things I co do inside the directive (controller). Many thanks for any solution.
Declare a method in the scope
$scope.getData=function(obj){
return obj > 3;
}
Then add this as filter in div
<div ng-repeat='thing in things | filter : getData' ng-if="$first">
<span >{{thing}}</span>
</div>
JSFIDDLE
If wanna to use this
Try like this
Declare a method in the scope
vm.getData=function(obj){
return obj > 3;
}
Then add this as filter in div
<div ng-repeat='thing in vm.things | filter : vm.getData' ng-if="$first">
<span >{{thing}}</span>
</div>
JSFIDDLE
You should have to create a filter or inline it like this:
<div ng-repeat='thing in ctrl.things' ng-if="thing > 3">
<span ng-if="$first">{{thing}}</span>
</div>
That should work
I think you are looking for this:
//controller
$scope.ctrl={};
$scope.ctrl.things=[{1:false},{2:false},{3:false},{4:true},{5:true}];
$scope.check=function(value){
$scope.count = value === true?($scope.count+1):$scope.count;
return $scope.count ===1 ;
}
//end of controller
HTML
<div ng-repeat='(key,value) in ctrl.things' >
<span ng-if="check(value)">{{key}}</span>
</div>
To show first element if you want to show last item you can put ng-if="$last"
I'm trying to construct an accordion list that shows more details when the accordion expands. Here is a simplified version of the template:
<body ng-controller="MainController as main">
<accordion>
<accordion-group ng-repeat="r in main.results" ng-controller="DetailsController as d">
<accordion-heading ng-click="d.getDetails(r.id)">
{{r.name}}
</accordion-heading>
<ul>
<li ng-repeat="v in d.details">{{v.detail}}</li>
</ul>
</accordion-group>
</accordion>
</body>
The DetailsController initially has an empty details array, but when the function getDetails() is called, that array is populated by a service (detailsService is simply an abstracted $resource call). This part works when not being applied to an accordion, but in this specific situation, nothing happens with the accordion heading is clicked. See below:
app.controller('DetailsController', function(detailsService) {
var vm = this
var details = []
var detailsPopulated = false
var getDetails = function(id) {
console.log('getDetails()')
if (!vm.detailsPopulated) {
console.log('Getting details')
detailsService.get({id: id}, function(data) {
vm.details = data.results
vm.detailsPopulated = true
});
}
}
return {
details: details,
getDetails: getDetails
}
});
This controller works in other cases, but for some reason, the ng-click on the accordion header does not invoke the getDetails function at all - if it did, I would see "getDetails()" in the console, since that is the first statement of the getDetails function.
Even simpler: setting up a controller with mock "details" doesn't work.
app.controller('DetailsController', function() {
var details = [{detail: 'Test'}]
return {
details: details
}
});
Template:
<body ng-controller="MainController as main">
<accordion>
<accordion-group ng-repeat="r in main.results" ng-controller="DetailsController as d">
<accordion-heading>
{{r.name}}
</accordion-heading>
<ul>
<li ng-repeat="v in d.details">{{v.detail}}</li>
</ul>
</accordion-group>
</accordion>
</body>
Not even this simplified example with the service and ng-click removed works.
Can anyone advise a solution? I am also trying to accomplish this using the "controller as" technique instead of using $scope everywhere.
You can not bind ng-click to <accordion-heading> beacause ui.bootstrap will use different DOM for heading. You can take a look at developer console to see what ui.bootstrap translate <accordion-heading> into DOM.
<div class="panel-heading">
<h4 class="panel-title">
<span class="ng-scope ng-binding">Header 1</span>
</h4>
</div>
I think you want to dynamically load the content of accordion. One way to achieve this is to $watch when the accordion is opened and perform loading. I have created this fiddle to demonstrate the idea. Something you must notice :
You can not put ng-controller inside accordion-group because it will raise error multiple directive asking for isolated scope. This is beacause <accordion-group> is an isolated scope and angular will not allow two scope : one from controller scope and one from directive isolated scope to bind into the same html. Reference. One way to work around it is to put a div with ng-controller and ng-repeat outside accordion-group
<div ng-repeat="r in main.results" ng-controller="DetailsController as d">
<accordion-group>
...
</accordion-group>
</div>
You can add attrs is-open to accordion-group and $watch for its change and perform loading. Accordion directive will change is-open value when you open or close the accordion.
Hope it helps.
I've a custom angular filter directive which can replace strings using the following syntax:
{{ 'MyValue' | replace: 'My':'Foo' }}
This works fine. Now I want to use this filter inside a ng-click
<button ng-click="alert('{{ 'MyValue' | replace: 'My':'Value'}}')">Click Me!</button>
This throws an parse exception (I assume because of the surrounding apostrophes from the alert). What's the correct syntax in this case?
A Plunkr is available here: http://plnkr.co/edit/xEGjY40LWORt5nlaJq46
here is the working Plunker
i added the controller and call a function inside controller when ng-click fired
<body ng-app="MyApp" ng-controller="x">
<p>{{ -3 | replace: '-':'n' }}</p>
<p>
<button ng-click="x('MyValue','replace','My','Value')">Click Me!</button>
</p>
</body>
in script.js
myApp.controller('x', function($scope, $filter) {
$scope.x = function(input,filterName,replaceStr,replaceBy) {
var filtered = $filter(filterName)(input,replaceStr,replaceBy);
alert(filtered);
}
});
for the more
ng-click='alert("1111")' dose not work because the when u put something inside ng-click, alert() in this case, it will check for $scope.alert so, alertis not work insideng-click`
As a rule, you cannot use interpolated values as a parameter to an executable attribute in angular ('&').
what you need to do is:
markup:
<button ng-click="alert(customValue)">Click Me!</button>
Controller code
$scope.customValue = $fitler('replace')('MyValue', 'My', 'Value');
I'd like to do something like this. The use case is I am showing a table with a configurable set of columns, each of which may have a filter associated with it. See this fiddle.
<div ng-app="">
<div ng-controller="MyCtrl">
{{money | filterStr}}
</div>
</div>
function MyCtrl($scope) {
$scope.money = 33;
$scope.filterStr = 'currency:"USD$"';
}
So as you can see, I basically want to store the filter string text as a scope variable, and then refer to it in the html by its name. This doesn't work, but is there a way to do something like this?
If you absolutely needed to save a reference to the filter dynamically within your controller $scope, you could create a reference to the filter function within a controller variable and then call it in the HTML like you would any other function or you could run the filter on your data in your controller and save the output to a variable. Here are two examples of doing this with the currency filter (JS Fiddle here):
<div ng-app="">
<div ng-controller="MyCtrl">
{{ moneyWithFilter }}
{{ currencyFilter(money, "USD$") }}
</div>
</div>
function MyCtrl($scope, currencyFilter) {
$scope.money = 33;
$scope.moneyWithFilter = currencyFilter($scope.money, "USD$");
$scope.currencyFilter = currencyFilter;
}
Notice that you have to append the string 'Filter' to the desired filter in order to inject it into your controller. You can read more about that here. I hope this helps!
I do something like this with
<a ng-click="setCurrent(m)">
{{m.name}}
</a>
<p ng-repeat="L in List | filter:current.name">
<a ng-click="add(w)">
{{w.Name}}
</a>
</p>
Then
function setCurrent(m) {
$scope.current = m;
}