ng-class not working in AngularJS when defined with scope variable - javascript

For my below code ng-class isn't working:
HTML
<div class="row-content" ng-controller="MainController">
<div class="tabs">
<div class="col-xs-6">
<h3 ng-class="{selected: searchType == 'news'}">
<a ng-click="SetSearchType('news')"
href="javascript:void(0)">Alumni News</a>
</h3>
</div>
<div class="col-xs-6">
<h3 ng-class="{selected: searchType == 'rss'}">
<a ng-click="SetSearchType('rss')"
href="javascript:void(0)">Firm News</a>
</h3>
</div>
</div>
</div>
AnjgularJS
var app = angular.module('ffApp', []);
app.controller('MainController', ['$scope', function($scope) {
$scope.searchType = 'news';
$scope.SetSearchType = function(type) {
$scope.searchType = type;
}
}]);

I think there is something wrong with your CSS styles or your $scope.selected param. Please check this runnable demo fiddle and carefully compare it with your solution:
View
<div class="row-content" ng-controller="MainController">
<div class="tabs">
<div class="col-xs-6">
<h3 ng-class="{'selected': searchType == 'news'}">
<a ng-click="SetSearchType('news')"
href="javascript:void(0)">Alumni News</a>
</h3>
</div>
<div class="col-xs-6">
<h3 ng-class="{'selected': searchType == 'rss'}">
<a ng-click="SetSearchType('rss')"
href="javascript:void(0)">Firm News</a>
</h3>
</div>
</div>
</div>
AngularJS
var myApp = angular.module('myApp', []);
myApp.controller('MainController', function($scope) {
$scope.searchType = 'news';
$scope.SetSearchType = function(type) {
$scope.searchType = type;
}
});
CSS
.selected a {
color:red;
}

put your class in quotes ('')
<div class="row-content" ng-controller="MainController">
<div class="tabs">
<div class="col-xs-6">
<h3 ng-class="{'selected': searchType == 'news'}">
<a ng-click="SetSearchType('news')" href="javascript:void(0)">Alumni News</a>
</h3>
</div>
<div class="col-xs-6">
<h3 ng-class="{'selected': searchType == 'rss'}">
<a ng-click="SetSearchType('rss')" href="javascript:void(0)">Firm News</a>
</h3>
</div>
</div>

Related

Getting all elements on a page and hiding them upon filter

I have something that filters groups of cards on a page that works well, until I try to add section headers to each group. Ideally, I'd like all the section headers to disappear when my "no results" block is displayed.
var $filterCheckboxes = $('input[type="checkbox"]');
$filterCheckboxes.on("change", function () {
$(".card-grid").show();
var selectedFilters = {};
$filterCheckboxes.filter(":checked").each(function () {
if (!selectedFilters.hasOwnProperty(this.name)) {
selectedFilters[this.name] = [];
}
selectedFilters[this.name].push(this.value);
});
var $filteredResults = $(".card");
$.each(selectedFilters, function (name, filterValues) {
$filteredResults = $filteredResults.filter(function () {
var matched = false,
currentFilterValues = $(this).data("category").split(" ");
$.each(currentFilterValues, function (_, currentFilterValue) {
if ($.inArray(currentFilterValue, filterValues) != -1) {
matched = true;
return false;
}
});
return matched;
});
});
$(".card").hide().filter($filteredResults).show();
var all_hidden = true;
$(".card").each(function (index) {
if ($(this).is(":visible")) {
all_hidden = false;
document.getElementsByClassName("no-results")[0].style.display = "none";
document.getElementsByClassName("section-header")[0].style.display =
"block";
}
});
if (all_hidden) {
$(".card-grid").hide();
document.getElementsByClassName("no-results")[0].style.display = "block";
document.getElementsByClassName("section-header")[0].style.display = "none";
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="filter-container">
<ul class="filters">
<li><input type="checkbox" name="topic" id="topic1" value="topic1"><label for="topic1">Topic 1
</li>
<li><input type="checkbox" name="topic" id="topic2" value="topic2"><label for="topic2">Topic 2</li>
<li><input type="checkbox" name="topic" id="topic3" value="topic3"><label for="topic3">Topic 3
</li>
</ul>
</div>
<div class="filter-section-content">
<div class="filter-container">
<ul class="filters">
<li><input type="checkbox" name="content-type" id="subfilter1" value="reads"><label for="subfilter1">subfilter1</label></li>
<li><input type="checkbox" name="content-type" id="subfilter2" value="linkedin"><label for="subfilter2">subfilter2</label></li>
<li><input type="checkbox" name="content-type" id="subfilter3" value="subfilter3"><label for="subfilter3">subfilter3</label>
</li>
</ul>
</div>
</div>
<p> </p>
<!--Cards-->
<!--Topic 1-->
<p class="section-header">Topic 1</p>
<div class="card-grid">
<!--New Card-->
<div class="card" data-category="topic1 subfilter1">
<div class="card-front-wrap">
<div class="card-front">
<p class="label">Topic 1</p>
<h1>Title</h1>
</div>
</div>
<div class="card-overlay">
<h5>More Info <i class="far fa-arrow-alt-circle-down fa-lg"></i></h5>
<div class="card-body">
</div>
</div>
</div>
<!--New Card-->
<div class="card" data-category="topic1 subfilter3">
<div class="card-front-wrap">
<div class="card-front">
<p class="label">Topic 1</p>
<h1>Title</h1>
</div>
</div>
<div class="card-overlay">
<h5>More Info <i class="far fa-arrow-alt-circle-down fa-lg"></i></h5>
<div class="card-body">
</div>
</div>
</div>
</div>
<!--Topic 2-->
<p class="section-header">Topic 2</p>
<div class="card-grid">
<!--New Card-->
<div class="card" data-category="topic2 subfilter1">
<div class="card-front-wrap">
<div class="card-front">
<p class="label">Topic 2</p>
<h1>Title</h1>
</div>
</div>
<div class="card-overlay">
<h5>More Info <i class="far fa-arrow-alt-circle-down fa-lg"></i></h5>
<div class="card-body"></div>
</div>
</div>
</div>
<div class="no-results">
No Results
</div>
I know that the [0] after the line that gets the class name for the section headers is only pulling in the first, but when I remove that then I get a "style is undefined" error. Shouldn't it be getting every element with the specified class name?
I use $(this).parent().prev(".section-header") to find out the header to set it show/hide when $(".card").each(function (index).
And by default, we should hide "no-results". Just show it if all_hidden = true.
So basically, I updated your codes into the below codes:
var all_hidden = true;
$(".card").each(function(index) {
if ($(this).is(":visible")) {
all_hidden = false;
// Show header if the card is visible
$(this).parent().prev(".section-header").show();
} else {
// Hide header if the card is invisible
$(this).parent().prev(".section-header").hide();
}
});
if (all_hidden) {
document.getElementsByClassName("no-results")[0].style.display = "block";
} else {
document.getElementsByClassName("no-results")[0].style.display = "none";
}
You can see full of demo here:
var $filterCheckboxes = $('input[type="checkbox"]');
$filterCheckboxes.on("change", function () {
$(".card-grid").show();
var selectedFilters = {};
$filterCheckboxes.filter(":checked").each(function () {
if (!selectedFilters.hasOwnProperty(this.name)) {
selectedFilters[this.name] = [];
}
selectedFilters[this.name].push(this.value);
});
var $filteredResults = $(".card");
$.each(selectedFilters, function (name, filterValues) {
$filteredResults = $filteredResults.filter(function () {
var matched = false,
currentFilterValues = $(this).data("category").split(" ");
$.each(currentFilterValues, function (_, currentFilterValue) {
if ($.inArray(currentFilterValue, filterValues) != -1) {
matched = true;
return false;
}
});
return matched;
});
});
$(".card").hide().filter($filteredResults).show();
var all_hidden = true;
$(".card").each(function (index) {
if ($(this).is(":visible")) {
all_hidden = false;
// Show header if the card is visible
$(this).parent().prev(".section-header").show();
} else {
// Hide header if the card is invisible
$(this).parent().prev(".section-header").hide();
}
});
if (all_hidden) {
document.getElementsByClassName("no-results")[0].style.display = "block";
} else {
document.getElementsByClassName("no-results")[0].style.display = "none";
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="filter-container">
<ul class="filters">
<li><input type="checkbox" name="topic" id="topic1" value="topic1"><label for="topic1">Topic 1
</li>
<li><input type="checkbox" name="topic" id="topic2" value="topic2"><label for="topic2">Topic 2</li>
<li><input type="checkbox" name="topic" id="topic3" value="topic3"><label for="topic3">Topic 3
</li>
</ul>
</div>
<div class="filter-section-content">
<div class="filter-container">
<ul class="filters">
<li><input type="checkbox" name="content-type" id="subfilter1" value="reads"><label for="subfilter1">subfilter1</label></li>
<li><input type="checkbox" name="content-type" id="subfilter2" value="linkedin"><label for="subfilter2">subfilter2</label></li>
<li><input type="checkbox" name="content-type" id="subfilter3" value="subfilter3"><label for="subfilter3">subfilter3</label>
</li>
</ul>
</div>
</div>
<p> </p>
<!--Cards-->
<!--Topic 1-->
<p class="section-header">Topic 1</p>
<div class="card-grid">
<!--New Card-->
<div class="card" data-category="topic1 subfilter1">
<div class="card-front-wrap">
<div class="card-front">
<p class="label">Topic 1</p>
<h1>Title</h1>
</div>
</div>
<div class="card-overlay">
<h5>More Info <i class="far fa-arrow-alt-circle-down fa-lg"></i></h5>
<div class="card-body">
</div>
</div>
</div>
<!--New Card-->
<div class="card" data-category="topic1 subfilter3">
<div class="card-front-wrap">
<div class="card-front">
<p class="label">Topic 1</p>
<h1>Title</h1>
</div>
</div>
<div class="card-overlay">
<h5>More Info <i class="far fa-arrow-alt-circle-down fa-lg"></i></h5>
<div class="card-body">
</div>
</div>
</div>
</div>
<!--Topic 2-->
<p class="section-header">Topic 2</p>
<div class="card-grid">
<!--New Card-->
<div class="card" data-category="topic2 subfilter1">
<div class="card-front-wrap">
<div class="card-front">
<p class="label">Topic 2</p>
<h1>Title</h1>
</div>
</div>
<div class="card-overlay">
<h5>More Info <i class="far fa-arrow-alt-circle-down fa-lg"></i></h5>
<div class="card-body"></div>
</div>
</div>
</div>
<!-- default hide no results -->
<div class="no-results" style="display: none">
No Results
</div>

jQuery - ordering divs in ascending order

So I have this code
var $divs = $("div.product");
$('#priceAscending').on('click', function() {
var ascendingOrderedDivs = $divs.sort(function(a, b) {
return $(a).find("div.price").text() > $(b).find("div.price").text();
});
$("#container").html(ascendingOrderedDivs);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrap">
<button id="priceAscending">Price ascending</button>
<!--<button id="priceDescending">Price descending</button>-->
<div id="container">
<div class="product">
<span id="name">Product One</span>
<div class="price">14.85$</div>
</div>
<div class="product">
<span id="name">Product Two</span>
<div class="price">27.59$</div>
</div>
<div class="product">
<span id="name">Product Three</span>
<div class="price">2.64$</div>
</div>
</div>
</div>
I want to sort div.product in ascending order based on the price, but it doesn't work. It puts 2.64 in the middle but it should put it first.
How can I fix this issue using jQuery?
You need to change > to -
return $(a).find("div.price").text() - $(b).find("div.price").text();
You also need to remove $ from price to compare the values. You can do it with str.slice(0, -1)
return $(a).find("div.price").text().slice(0, -1) - $(b).find("div.price").text().slice(0, -1);
Here is a working JSFiddle
I suggest using the numeric value instead of the string
var divs = $("div.product");
$('#priceAscending').on('click', function() {
var ascendingOrderedDivs = divs.sort(function(a, b) {
var aVal = parseFloat($(a).find("div.price").text().replace("$",""));
var bVal = parseFloat($(b).find("div.price").text().replace("$",""));
return aVal - bVal;
});
$("#container").html(ascendingOrderedDivs);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrap">
<button id="priceAscending">Price ascending</button>
<!--<button id="priceDescending">Price descending</button>-->
<div id="container">
<div class="product">
<span id="name">Product One</span>
<div class="price">14.85$</div>
</div>
<div class="product">
<span id="name">Product Two</span>
<div class="price">27.59$</div>
</div>
<div class="product">
<span id="name">Product Three</span>
<div class="price">2.64$</div>
</div>
</div>
</div>
You could replace the $ at the end of the prices with an empty string and use parseFloat to compare the values. Note that id's on the page should be unique. For all the spans you use id="name
var $divs = $("div.product");
$('#priceAscending').on('click', function() {
var ascendingOrderedDivs = $divs.sort(function(a, b) {
return parseFloat($(a).find("div.price").text().replace(/\$$/, '')) - parseFloat($(b).find("div.price").text().replace(/\$$/, ''));
});
$("#container").html(ascendingOrderedDivs);
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="wrap">
<button id="priceAscending">Price ascending</button>
<!--<button id="priceDescending">Price descending</button>-->
<div id="container">
<div class="product">
<span id="name">Product One</span>
<div class="price">14.85$</div>
</div>
<div class="product">
<span id="name">Product Two</span>
<div class="price">27.59$</div>
</div>
<div class="product">
<span id="name">Product Three</span>
<div class="price">2.64$</div>
</div>
</div>
</div>

remove parent if no list element has children

On my Website I have a list with different classes which maybe have content or not. If all of them are empty the whole container should be removed, but if one or more have content inside, nothing should happen.
Code Snippets:
<div class="fts">
<div class="panel-heading">...</div>
<div class="panel-collapse">
<div class="panel-body">
<div class=" bd-layoutbox-16 clearfix">
<div class="bd-container-inner">
<h5>Heading 5</h5>
<div>...</div>
</div>
</div>
<div class=" bd-layoutbox-84 clearfix">
<div class="bd-container-inner"></div>
</div>
<div class=" bd-layoutbox-31 clearfix">
<div class="bd-container-inner"></div>
</div>
<div class=" bd-layoutbox-82 clearfix">
<div class="bd-container-inner"></div>
</div>
<div class=" bd-layoutbox-85 clearfix">
<div class="bd-container-inner"></div>
</div>
<div class=" bd-layoutbox-86 clearfix">
<div class="bd-container-inner"></div>
</div>
<div class=" bd-layoutbox-87 clearfix">
<div class="bd-container-inner"></div>
</div>
<div class=" bd-layoutbox-88 clearfix">
<div class="bd-container-inner"></div>
</div>
<div class=" bd-layoutbox-89 clearfix">
<div class="bd-container-inner"></div>
</div>
<div class=" bd-layoutbox-90 clearfix">
<div class="bd-container-inner"></div>
</div>
</div>
</div>
</div>
JS
$(".bd-layoutbox-84, .bd-layoutbox-31, .bd-layoutbox-82, .bd-layoutbox-85, .bd-layoutbox-86, .bd-layoutbox-87, .bd-layoutbox-88, .bd-layoutbox-89, .bd-layoutbox-90")
.each(function(){
if($(this).has("h5").length == 0){
$(this).parent().parent().parent().remove();
}
});
What's the problem?
Thanks for help.
You may need to rework your logic a bit by creating a function, but here's a thought ..
var removethis=1;
$(".bd-layoutbox-84, .bd-layoutbox-31, .bd-layoutbox-82, .bd-layoutbox-85, .bd-layoutbox-86, .bd-layoutbox-87, .bd-layoutbox-88, .bd-layoutbox-89, .bd-layoutbox-90")
.each(function(){
if($(this).has("h5").length > 0){
removethis = 0;
}
});
if (removethis == 1) {
// remove parent item here
}
You can use contains selector to check any content there or not and then remove it. Below is the code
$('div.fts').each(function() {
var $this = $(this);
if ($this.find('div[class*="bd-layoutbox-"] h5').length === 0) {
$this.remove();
}
});
Demo: https://jsfiddle.net/6bh0d9yo/1/

AngularJS: ng-switch + ng-repeat with button inside of switch statement

I'm pretty new to angular and I'm kind of stuck with an issue. I have an ng-repeat that shows items. In the items I have a "show more info" button, which when you click it should cause the a new view to replace the current one (including the show more info button). The new view would then have a "go back" button which will switch back to the original state.
Unfortunately I can't seem to figure out how to get this to work.
This is as far as I've gotten...
<article ng-repeat="item in items" class="items">
<div ng-switch on="view">
<div ng-switch-default>
<p>Default State for {{item}}</p>
<div class="btn">More Info
</div>
<div ng-switch-when="info">
<p>Info for {{item}}</p>
<div class="btn">Go back</div>
</div>
</div>
</article>
If someone could help me out here I would appreciate it. Thank you.
You can set the value of view when button is clicked. I would advise you to use item.view instead of view, it will prevent view of other elements to be toggled.
<article ng-repeat="item in items" class="items">
<div ng-init="viewDefaultValue = item.view;" ng-switch on="item.view">
<div ng-switch-default>
<p>Default State for {{item}}</p>
<div class="btn" ng-click="item.view = 'info';">More Info</div>
</div>
<div ng-switch-when="info">
<p>Info for {{item}}</p>
<div class="btn" ng-click="item.view = viewDefaultValue;">Go back</div>
</div>
</div>
</article>
Here is an working example.
(function() {
angular
.module('myApp', [])
.controller('myController', function($scope) {
$scope.items = [{
view: '',
text: 'item1'
}, {
view: '',
text: 'item2'
}]
});
})();
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="myApp" ng-controller="myController">
<div ng-repeat="item in items" class="items">
<div ng-init="viewDefaultValue = item.view;" ng-switch on="item.view">
<div ng-switch-default>
<p>Default State for {{item.text}}</p>
<div class="btn" ng-click="item.view = 'info';">More Info
</div>
</div>
<div ng-switch-when="info">
<p>Info for {{item.text}}</p>
<div class="btn" ng-click="item.view = viewDefaultValue;">Go back</div>
</div>
</div>
</div>
use ng-hide and ng-show instead of ng-switch
<article ng-repeat="item in items" class="items">
<div ng-show="isviewvisible">
<div>
<p>Default State for {{item}}</p>
<div class="btn" ng-click="more()">More Info
</div>
<div ng-hide="isviewvisible">
<p>Info for {{item}}</p>
<div class="btn" ng-click="goBack()">Go back</div>
</div>
</div>
</article>
now in angularjs
$scope.isviewvisible = true;
$scope.more = function(){
$scope.isviewvisible = false;
}
$scope.goBack = function(){
$scope.isviewvisible = true;
}
when you clicked the more() it will hide the view and will show the moreinfo
when you click the goBack() it will hide the moreifo and will show the view

angularJS pass variable to ui.bootstrap template

In my view i have such code:
<script id="template/accordion/accordion.html" type="text/ng-template">
<div class="panel-group" data-ng-transclude></div>
</script>
<script id="template/accordion/accordion-group.html" type="text/ng-template">
<div class="panel panel-default">
<div class="panel-heading custom">
<h4 class="panel-title custom">
<a href accordion-transclude="heading" data-ng-click="toggleOpen();"><span>{{heading}}</span></a>
</h4>
</div>
<div class="panel-collapse" collapse="!isOpen">
<div class="panel-body" data-ng-transclude></div>
</div>
</div>
</script>
<script type="text/ng-template" id="nodes_renderer.html">
<accordion close-others="false">
<accordion-group>
<accordion-heading>
{{node.Title}}
</accordion-heading>
<div data-ng-bind-html="node.Text"></div>
<ol ui-tree-nodes="" data-ng-model="node.Childs">
<li data-ng-repeat="node in node.Childs" ui-tree-node data-ng-include="'nodes_renderer.html'">
</li>
</ol>
</accordion-group>
</accordion>
</script>
<div ui-tree="options">
<ol ui-tree-nodes data-ng-model="articles">
<li data-ng-repeat="node in articles" ui-tree-node data-ng-include="'nodes_renderer.html'"></li>
</ol>
</div>
is it real to get node.Options.length, when i try to render header here:
<div class="panel-heading">
<h4 class="panel-title">
<a href accordion-transclude="heading" data-ng-click="toggleOpen();" class="no-link"><span>{{heading}}</span></a>
</h4>
</div>
and then if my node.Options are higher then 0 i do ng-class...
how could i pass variable to non-my directive template?
also i must pass there whole node object, so that i could edit it etc...
Every directive lives within a scope. I had a similar case where I wrote a common pager directive that pulls its details from the Controller scope. My templates are externalized, but this does not affect the functionality.
Directive usage:
<div class="row" ng-controller="TableController">
<table-pager></table-pager>
</div>
Directive definition:
angular.module.directive('tablePager', function() {
return {
restrict: 'E',
replace: true,
templateUrl: 'templates/table-pager.html'
};
})
Controller:
angular.module.controller('TableController', function($scope, $log, $location) {
$scope.query = {};
$scope.limit = 20;
$scope.offset = 0;
$scope.currentPage = 0;
$scope.total = 0;
...
}
Template code of templates/table-pager.html (snippet):
<div class="row">
<div class="col-md-4">{{total}} Entries found</div>
<div class="col-md-4 col-pager">...</div>
</div>
You can read more about AngularJS custom directives at http://tutorials.jenkov.com/angularjs/custom-directives.html
HTH

Categories

Resources