AngularJS ng-if inside ng-repeat does not work - javascript

Here is my code:
<body ng-controller="QueryCntl">
<div>
<h1> Target:{{target}}</h1>
</div>
<div ng-app="myApp" ng-controller="mytableCtrl">
<div ng-include="'header.html'"></div>
<div id="menuList">
<ul class="menuNav">
<li class="menuList_Slide" ng-repeat="x in names">
<div>
{{ x.category }}
</div>
<div ng-if="{{target}} == {{x.id}}"> //Display subcategory if true
<ul id="subCategories">
<li>
Childid should be displayed
</li>
</ul>
</div>
</li>
</ul>
</div>
</div>
<script>
var app = angular.module('myApp', [], function($locationProvider) {
$locationProvider.html5Mode(true);
});
function QueryCntl($scope, $location) {
$scope.target = $location.search()["categoryid"];
}
app.controller('mytableCtrl', function($scope, $http) {
$http.get("api/topCategories")
.success(function(response) {$scope.names = response;});
});
</script>
I want to display only 1 subcategory if {{target}} is equal to {{x.id}}. But for now it prints everything... {{target}} gets value from the url where ?categoryid=some_number and x.id is a value from DB. These values works fine in my code.
I would appreciate any help.
EDIT: ng-if="target == x.id" does not help.

ngIf doesn't need to use {{}} - it's already an Angular expression:
div ng-if="target == x.id"

Problem solver:
I inserted
<base href="category.html">
in head tags and deleted bad script source.

You don't need to interpolate properties within the ng-if directive's conditional as Angular evaluates the complete expression against the scope already. Try this:
ng-if="target == x.id"

Replace:
<div ng-if="{{target}} == {{x.id}}">
With:
<div ng-if="target == x.id">
The ng-if attribute should contain plain JavaScript, instead of those interpolation tags ({{}}).
This holds true for all ng- attributes.

ngIf directive expects an expression, so you don't need interpolation tags:
<div ng-if="target == x.id"> //Display subcategory if true
<ul id="subCategories">
<li>
Childid should be displayed
</li>
</ul>
</div>
And one more thing: you are not initializing $scope.target because corresponding controller is outside of the ng-app. Remove ng-controller="QueryCntl" and add target initialization into mytabeCtrl:
app.controller('mytableCtrl', function($scope, $http) {
$scope.target = $location.search()["categoryid"];
$http.get("api/topCategories")
.success(function(response) {$scope.names = response;});
});

Related

how to ng-show specific element inside list item on ng-click?

how to show iframe element inside li on ng-click, for just the specific clicked one?
And hide all iframes, using AngularJs.
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.6.4/angular.min.js"></script>
<script>
var app = angular.module("myApp", []);
app.controller("myCtrl", function ($scope, $http, $sce) {
var indx;
$scope.PlayFun = function (order) {
indx = order;
// I need this fuction because I do a lot of things inside
};
});
</script>
<div data-ng-app="myApp" data-ng-controller="myCtrl">
<ul style="list-style-type: none">
<li data-ng-click="PlayFun($index)" data-ng-repeat="x in records">
<div data-ng-if="indx === $index">
<iframe id="video" style="width: 100%; height: 300px;"
data-ng-src="{{videoSource}}" allowfullscreen>
</iframe>
</div>
</li>
</ul>
</div>
all I need in other words:
I need by clicking li the PlayFun would be executed. and by $index the iframe get displayed.
Instead of assigning the value to indx variable you should create a property in $scope as follows
$scope.PlayFun = function (order) {
$scope.indx = order;
};
We can access the properties and methods of $scope in our HTML.

Show HTML elements in JSON with Angular js

I am new in angular js, I am trying to format a json data with angular js.
Here is my json data
[
{"field_add_link": "Home"},
{"field_add_link": "About Us"}
]
here is my conroller
var myApp = angular.module('myApp', ['ngSanitize']);
myApp.controller('myController',function($scope, $http) {
$http.get('http://localhost/drupal3/menu')
.then(function(response) {
$scope.links = response;
});
});
and finally here is how i am fetching the json data with angular
<div class="col-md-8 content" ng-controller ="myController">
<div class="col-md-12" ng-repeat="link in links" ng-bind-html="links">
<p>{{ link.field_add_link }}</p>
</div>
</div>
no output was shown after this, giving an error Error: [$sce:unsafe] Attempting to use an unsafe value in a safe context. in the browser's console
but when I used ng-bind-html="links[0].field_add_link instead of ng-bind-html="links" and <p>{{ link[0].field_add_link }}</p> instead of <p>{{ link.field_add_link }}</p>
then i get Home as output 'without interpreting the tag'
Pls, how do I go about this?
First of all you dont need the ng-bind-html attribute on your div with ng-repeat. It should be on your p tag. Second, you need to bind link (the current element of the ng-repeat-loop) not links (the array). Although you need to look into the error [$sce:unsafe]. HTMl can only be bind to an element-body if it is trusted. For that you need to have, for example, a filter.
myApp.filter ('to_trusted', ['$sce', function ($sce) {
return function (text) {
return $sce.trustAsHtml (text);
};
}]);
<div class="col-md-8 content" ng-controller ="myController">
<div class="col-md-12" ng-repeat="link in links">
<p ng-bind-html="link.field_add_link | to_trusted"></p>
</div>
</div>
You just need to move your ng-bind-html from div to <p> like following code.
<p ng-bind-html="link.field_add_link"></p>
var myApp = angular.module('myApp', ['ngSanitize']);
myApp.controller('myController', function($scope, $http) {
var data = [{"field_add_link": "Home"},
{"field_add_link": "About Us"}];
$scope.links = data;
//For demo, removed the http call
});
<head>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.6.5/angular-sanitize.js"></script>
</head>
<body ng-app="myApp">
<div class="col-md-8 content" ng-controller="myController">
<div class="col-md-12" ng-repeat="link in links">
<p ng-bind-html="link.field_add_link"></p>
</div>
</div>
</body>

Angularjs show hide css issue

I had a hard issue figuring out on how to hide and show icon/text with angular code. I am completely new to angular and tried hard on the below fiddle code. How do I hide + or minus icon with .closest in such dom scenarios.
<div ng-controller="MyCtrl">
{{name}}
<div data-toggle="collapse" aria-expanded="true" data-target="#list-item-line-0" id="expandCollapseChild" ng-click="addExpandCollapseChildIcon()">
<div>
<div>
<label>
<div>
<span class="icon-expand">-</span>
<span class="icon-collapse">+</span>
</div>
<div>
Click me to hide minus icon
</div>
</label>
</div>
</div>
</div>
</div>
var myApp = angular.module('myApp', []);
function MyCtrl($scope) {
$scope.name = 'Superhero';
$scope.addExpandCollapseChildIcon = function() {
alert('');
if (angular.element('#expandCollapseChild').hasClass('collapsed')) {
angular.element(this).closest('.icon-collapse').css('display', 'none');
} else {
if (angular.element('#expandCollapseChild').hasClass('collapsed')) {
angular.element(this).closest('.icon-collapse').css('display', 'block');
}
}
}
In Angular, this is the wrong approach. You shouldn't actually show or hide elements inside the controller. That's applying a jQuery style (working directly on the DOM) to Angular.
In Angular, you'd use something like ng-if, ng-show or ng-class, all of which can link back to a property on the scope object that is accessible via the controller.
Here are some examples:
<div ng-if="myProp === 'ShowMe'">
<div ng-show="myProp === 'ShowMe'">
<div ng-class="{myCssClass: myProp === 'ShowMe'">
Inside your controller, you'd have something like this:
function MyCtrl($scope) {
$scope.myProp = 'ShowMe';
$scope.addExpandCollapseChildIcon = function(newPropValue) {
$scope.myProp = newPropValue;
}
}
Here's some links to documentation on ng-if, ng-show and ng-class:
https://docs.angularjs.org/api/ng/directive/ngIf
https://docs.angularjs.org/api/ng/directive/ngShow
https://docs.angularjs.org/api/ng/directive/ngClass
AngularJS has a bunch of angulary ways of doing things, your question for example might look like this:
var app = angular.module("app", []);
app.controller("ctrl", function($scope) {
$scope.collapsed = true;
})
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="ctrl">
<span ng-bind="collapsed ? '+' : '-'"></span>
</div>
</div>
It watches a model and changes it's appearance based on that model using the ternary operator within ng-bind.
The way you defined your app and controller was incorrect. There's a bunch of different ways to do this as you can see from the answers.
I took this approach:
<div ng-app='myApp' ng-controller="MyCtrl">
{{name}}
<div>
<div>
<div>
<label>
<div>
<span ng-show='(collapsed != false)' class="icon-expand">-</span>
<span ng-show='(collapsed == false)' class="icon-collapse">+</span>
</div>
<div ng-click='collapsed = !collapsed'>
Click me to hide minus icon
</div>
</label>
</div>
</div>
</div>
</div>
<script>
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function ($scope) {
$scope.name = 'Superhero';
$scope.collapsed = false;
});
</script>
Create a scoped variable that indicated whether or not it is collapsed . Then change that variable and the ng-shows will react.

Access a ng-repeat scope from a controller

I'm trying to display some comment with two nested ng-repeat:
<div ng-repeat="element in elements" >
<ul>
<!-- comments -->
<li ng-repeat="comment in comments">
<span>Comment</span> <strong>{{comment.username}}</strong>
<blockquote>{{comment.content}}</blockquote>
</li>
</ul>
</div>
Here's what's in the controller:
$scope.comments = [];
$scope.populateComments = function(content_id){
ProjectsService.commentsQuery(content_id)
.then(function (data) {
$scope.comments = data;
})
}
$scope.populateComments(element.id);
Obviously it's not working, my problem is that I don't know how, nor if it's possible, to access the property of an object of the ng-repeat scope (to get element.id and get only the comments related to the element involved).
Any ideas?
Thank you in advance!
You can access the property of an object of the ng-repeat scope. You need to re-factor your code.
In Html
<div ng-repeat="element in elements" >
<ul>
<!-- comments -->
<li ng-repeat="comment in element.comments">
<span>Comment</span> <strong>{{comment.username}}</strong>
<blockquote>{{comment.content}}</blockquote>
</li>
</ul>
</div>
In JS
$scope.populateComments = function(element){
ProjectsService.commentsQuery(element.id)
.then(function (data) {
element.comments = data;
})
}
$scope.populateComments(element);

angular.js ng-repeat li items with html content

I have a model that comes back from the server which contains html instead of text (for instance a b tag or an i tag)
when I use ng-repeat to built a list out of it it shows the html as pure text, is there a built in filter or directive that put's the html inside the li items or not? I've looked in the documentation but since I'm still very new to it I'm having difficulties finding it.
ng-repeat:
<li ng-repeat="opt in opts">
JSFiddle:
http://jsfiddle.net/gFFBa/1/
It goes like ng-bind-html-unsafe="opt.text":
<div ng-app ng-controller="MyCtrl">
<ul>
<li ng-repeat=" opt in opts" ng-bind-html-unsafe="opt.text" >
{{ opt.text }}
</li>
</ul>
<p>{{opt}}</p>
</div>
http://jsfiddle.net/gFFBa/3/
Or you can define a function in scope:
$scope.getContent = function(obj){
return obj.value + " " + obj.text;
}
And use it this way:
<li ng-repeat=" opt in opts" ng-bind-html-unsafe="getContent(opt)" >
{{ opt.value }}
</li>
http://jsfiddle.net/gFFBa/4/
Note that you can not do it with an option tag: Can I use HTML tags in the options for select elements?
Note that ng-bind-html-unsafe is no longer suppported in rc 1.2. Use ng-bind-html instead. See: With ng-bind-html-unsafe removed, how do I inject HTML?
You can use NGBindHTML or NGbindHtmlUnsafe this will not escape the html content of your model.
http://jsfiddle.net/n9rQr/
<div ng-app ng-controller="MyCtrl">
<ul>
<li ng-repeat=" opt in opts" ng-bind-html-unsafe="opt.text">
{{ opt.text }}
</li>
</ul>
<p>{{opt}}</p>
</div>
This works, anyway you should be very careful when using unsanitized html content, you should really trust the source of the content.
use ng-bind-html-unsafe
it will apply html with text inside like below:
<li ng-repeat=" opt in opts" ng-bind-html-unsafe="opt.text" >
{{ opt.text }}
</li>
Here is directive from the official examples angular docs v1.5 that shows how to compile html:
.directive('compileHtml', function ($compile) {
return function (scope, element, attrs) {
scope.$watch(
function(scope) {
return scope.$eval(attrs.compileHtml);
},
function(value) {
element.html(value);
$compile(element.contents())(scope);
}
);
};
});
Usage:
<div compile-html="item.htmlString"></div>
It will insert item.htmlString property as html any place, like
<li ng-repeat="item in itemList">
<div compile-html="item.htmlString"></div>
If you want some element to contain a value that is HTML, take a look at ngBindHtmlUnsafe.
If you want to style options in a native select, no it is not possible.
ng-bind-html-unsafe is deprecated from 1.2. The correct answer should be currently:
HTML-side: (the same as the accepted answer stated):
<div ng-app ng-controller="MyCtrl">
<ul>
<li ng-repeat=" opt in opts" ng-bind-html-unsafe="opt.text">
{{ opt.text }}
</li>
</ul>
<p>{{opt}}</p>
</div>
But in the controller-side:
myApp.controller('myCtrl', ['$scope', '$sce', function($scope, $sce) {
// ...
$scope.opts.map(function(opt) {
opt = $sce.trustAsHtml(opt);
});
}

Categories