ng-class not working in one situation. What are some possible cause of this? - angularjs

I'm stuck. Cannot figured this out. This question is very simple to show, but I'm not really sure how to put it as a question, therefore I'll try my best.
First, here's the layout of my whole app (The problem lies in the Header.jsp):
<jsp:include page="../home/Header.jsp" />
<jsp:include page="../home/Modals.jsp" />
<div data-ng-view data-save-scroll-position data-position-relative-to-menu></div>
<jsp:include page="../home/Footer.jsp" />
The problem is very simple. I have the following data-ng-class in the data-ng-view section that change a tab to active if something is true (The problem is it won't work in one scenario even though it displayed true in the tab name):
<ul class="nav nav-tabs">
<li role="presentation" data-ng-class="tab.isSelected ? 'active' : ''" data-ng-repeat="tab in ctrl.tabs"
data-ng-click="ctrl.fetchBIReports(tab)">
</li>
</ul>
In the JSP that use data-ng-include for the above markup, there's a side nav to change to this page. Once clicked this side-nav, it highlighted the tab 'active' as expected (trying not to include the whole jsp):
<div class="side-navbar">
<ul>
<li class="{{ ctrl.navigate.path == 'bi/schedule' ? 'active-link' : 'normal-link'}}">
Schedule Reports
</li>
</ul>
</div>
<div class="content-right" data-ng-include="ctrl.navigate.path"></div>
content-right includes the JSP mentioned in the second markup.
So far, so good. Here's a demo of it working (including both side-navbar and content-right):
The problem is, in my Header.jsp, there's a nav bar that takes me to the same page. If it is clicked from a different page with different controller, then it works. But if I'm in the current controller and click that nav bar link, then data-ng-class does not take 'active' as its class. Here's the markup for the Header.jsp for that link:
<li class="dropdown" data-roles="['ROLE_ADMIN']">
<a href="#/bi" class="dropdown-toggle" data-toggle="dropdown" data-ng-click="ctrl.changeNavigation('bi/schedule')"
role="button" aria-haspopup="true" aria-expanded="false">BI Management<span class="caret"></span></a>
<ul class="dropdown-menu">
<li>Schedule Reports</li>
</ul>
</li>
Here is the demo of it not working even though it is printing out true in the UI:
The only problem is with this UI. All the data are populated. Records are displayed for the correct tab. Even side nav-bar is displaying the correct active class.

Your syntax for ng-class is off a bit. The format is "{ '[class-name]': [expression that evaluates to true or false] }". You can have multiple class values separated by commas each with their own expression. When an expression is true, the corresponding class is applied to the element and when it is false the class is removed from the element. The way you have written it would almost work for the plain class attribute, but you would need to include the interpolation characters: {{ and }}. Here is a very simple example to illustrate ng-class.
angular.module('app', []);
.red {
color: #fff;
background-color: #e21d1d;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.7.5/angular.min.js"></script>
<div ng-app="app">
<label>
<input type="checkbox" ng-model="applyRedClass" /> Apply 'red' class
</label>
<div ng-class="{'red': applyRedClass}">
This is a simple example of how to use ng-class.
</div>
</div>

Related

toggle extra detail for a record inside an ngRepeat

I'm working on a project where the client has supplied a pile of html where I need to plugin the data from our database and have hit a problem that I'm finding difficult to solve....
So first problem is with routing
<div ng-repeat="class in vm.classes">
<div class="class-overview">
<a href="#">
<span class="class-title">{{class.description}}</span>
... more stuff here
</a>
</div>
<div class="class-information collapse">
<div class="full-width">
{{class.longDescription}}
</div>
</div>
</div>
he has supplied some javascript to handle the click on class-overview
$('.class-overview a').on('click',function(e) {
e.preventDefault();
});
$('.class-overview').on('click',function() {
$('.class-overview.active').removeClass('active').next('.class-information').collapse('hide');
$(this).addClass('active').next('.class-information').collapse('show');//.css('top',offset).collapse('show');
});
and i have a line like this in my state provider
// default route
$urlrouterProvider.otherwise("/")
So the problem is that the ui-router handles the click and sends me back to the home page.
The ideal solution is to leave as much of his markup intact, so can anyone tell me how I stop ui-router handling the click?
or failing that, how I might use ng-click and ng-show to get the same effect, i.e. hiding and showing the class-information div...
If I understand well your question, you want to display the .class-information div when you click on the .class-overview element.
That can be done by using a variable in a ng-show like this:
<div ng-repeat="class in vm.classes">
<div class="class-overview">
<a href="#" ng-click="display = !display">
<span class="class-title">{{class.description}}</span>
... more stuff here
</a>
</div>
<div class="class-information" ng-show="display">
<div class="full-width">
{{class.longDescription}}
</div>
</div>
</div>
The display variable will be falsy when you land on the page, therefore the ng-click will be executed, this variable will be set to true.
I see that you are using a collapse class to hide the content if it is collapsed. Then you could use angular ng-class to put the collapse class when the display variable is false. Your div.class-information would look like this:
<div class="class-information" ng-class="{collapse: !display}">
<div class="full-width">
{{class.longDescription}}
</div>
</div>

Set css class to list options dynamically AngularJS

Well there are two list options in my code - Monthly and quarterly
I have one class "active" which generally highlights the element.
I need class "active" should be applied to one of the options when they are clicked or selected. Here class=active is applied to only Monthly manually.
Looking for Angular solution for this.
<div class="list">
<p class="subheader secondary">Select Preferred View</p>
<ul class="tabs">
<li><a href="#monthly" ng-click="type='month'" data-ajax="false" **class=active**>Monthly</a></li>
<li>Quarterly</li>
</ul>
</div>
Use ng-class directive like in a code below.
<div class="list">
<p class="subheader secondary">Select Preferred View</p>
<ul class="tabs">
<li><a href="#monthly" ng-click="type='month'" ng-class="{'active' : type=='month'}" data-ajax="false" **class=active**>Monthly</a></li>
<li>Quarterly</li>
</ul>
</div>
It adds specified class when expression given after classname evaluates to true and removes it when it evaluates to false.
ng-class="{'classname' : expression}"
You can set a default value in a controller:
$scope.type = 'month';
or via ng-init directive on div:
<div class="list" ng-init="type='month'">
jsfiddle with example
jsfiddle with setting default in ng-init

Bind different dom elements in Angular

I have this HTML
<div class="pageContent">
<aside class="left-cont">
<ul class="btn-menu" >
<li ng-repeat="tab in tabs" ><a class="ng-scope ng-binding" href="#" ng-click="show={{tab.id}}"> {{tab.name}}</a> </li>
</ul>
</aside>
<section class="main-content" ng-show="show === 1">
<h1> {tab.title}}</h1>
<p>{{tab.content}}</p>
</section>
<section class="main-content" ng-show="show === 2">
<h1> {{tab.title}}</h1>
<p>{{tab.content}}</p>
</section>
<section class="main-content" ng-show="show === 3">
<h1> {{tab.title}}</h1>
<p>{{tab.content}}</p>
</section>
</div>
And I have three problems with it:
1)ng-click="show={{tab.id}}"shows me the right id number in the dom, for instance, id=1 does show <a class="ng-scope ng-binding" href="#" ng-click="show=1">but I do get an error in my console - Error: [$parse:syntax] http://errors.angularjs.org/1.3.8/$parse/syntax?p0=%7B&p1=invalid%20key&p2=7&p3=show%3D%7B%7Btab.id%7D%7D&p4=%7Btab.id%7D%7D Why is that? I have tried to to write tab.id instead of {{tab.id}}, but it doesn't even fetch the element.
2) I want the section tags to be appended whenever there's a click on the a, but I can not do so since the section tags aren't wrapped in the li tags (when I do put them in the li they do fire, but that's not what I want). How do I bind these two different elements?
3) I want each section to append the content of its specific tab for the section that has - ng-show="show === 1" I want tab.title and tab.content of the tab that has the id=1, and so on..
How is that all possible?
Help is very much appreciated here
#HarishR is right: this is not the AngularJS way to do things. The imperative way of doing things would be to have an ng-click set the isActive property to true on an instance of tab.
Then the directive would would watch the isActive property and change class accordingly.
Since you probably don't want to reinvent the wheel, you could consider using Angular strap ( http://mgcrea.github.io/angular-strap/#/tabs#tabs ) or check out this code https://github.com/angular-ui/bootstrap/blob/master/src/tabs/tabs.js.

How to change the content of a tab while you are on the same tab using AngularJS and Bootstrap?

Using AngularJS and Bootstrap, let say there are 3 tabs: tab1, tab2, and tab3. There are also some links on each tabs. Now for example, tab1 is active. The question is: how to change the content of the tab1 by clicking a link within the same tab?
main.html:
<div class="tabbable">
<ul class="nav nav-tabs">
<li ng-class="{active: activeTab == 'tab1'}"><a ng-click="activeTab = 'tab1'" href="">tab1</a></li>
<li ng-class="{active: activeTab == 'tab2'}"><a ng-click="activeTab = 'tab2'" href="">tab2</a></li>
<li ng-class="{active: activeTab == 'tab3'}"><a ng-click="activeTab = 'tab3'" href="">tab3</a></li>
</ul>
</div>
<div class="tab-content">
<div ng-include="'/'+activeTab"></div>
</div>
tab1.html:
<h1>TAB1</h1>
Something
something.html
<h1>SOMETHING</h1>
Now the question is how to change the tab1 content to something.html while the tab1 is active?
As pointed out in other examples there are many ways to do this. Direct DOM manipulation is not really the Angular way of thinking about this kind of use case. A better way to think about it might be:
What possible content can this tab contain?
What will control its' being displayed?
Using the ng-if or ng-switch directive allows you to selectively limit the content based on a variable defined in the scope.
Consider this possibility:
<div class="tabbable">
<ul class="nav nav-tabs">
<li ng-class="{active: activeTab == 'tab1'}"><a ng-click="activeTab = 'tab1'" href="">tab1</a></li>
<li ng-class="{active: activeTab == 'tab2'}"><a ng-click="activeTab = 'tab2'" href="">tab2</a></li>
<li ng-class="{active: activeTab == 'tab3'}"><a ng-click="activeTab = 'tab3'" href="">tab3</a></li>
</ul>
</div>
Based on your code for the included file you could do this:
<div class="tab-content">
<div ng-if="content==='A'" ng-include="'/'+activeTabA"></div>
<div ng-if="content==='B'" ng-include="'/'+activeTabB"></div>
</div>
Another approach is to utilize ng-view and routing. It is more complicated than conditionally including but less complicated than writing a whole new directive.
In short, you define a container element with the ng-view attribute like this
<div ng-view></div>
Then set up a routing table in your javascript code like this
$routeProvider.when('/tab1', {templateUrl: 'partials/tab1.html', controller: 'tab1Controller'});
$routeProvider.when('/tab2', {templateUrl: 'partials/tab2.html', controller: 'tab2Controller'});
For more detail see this link: http://docs.angularjs.org/api/ngRoute.directive:ngView
This is actually a fairly common AngularJS issue, and is handled pretty nicely by nested directives. It works well enough that it's actually one of the demos in the Custom Directive Guide on the AngularJS docs page. It's the last example, "Creating Directives that Communicate". You can see the full code there, but the idea is that you create a 'container' directive for the tab group and a 'pane' directive for the inside content. Your HTML ends up looking like this:
<my-tabs>
<my-pane title="Hello">
<h5 id="pane1">Hello</h5>
<p>This content is in the first pane.</p>
</my-pane>
<my-pane title="World">
<h5 id="pane2">World</h5>
<em>This content is in the second pane.</em>
</my-pane>
</my-tabs>
As #musically_ut pointed out in his comment, there are a lot of ways to handle this. This is just one way, but I think it works out pretty well.

Angular: Show Form Elements when select is valid after on change shows all hidden form elements in loop instead only the one which select was changed

i repeat things in ng repeat like so
<div class="" ng-repeat="deutscheBankEvent in deutscheBankEvents">
<div class="schrottler-opened schrottler" title="">
<span class="presse_ueber" style="font-size:22px;margin-left:10px;font-weight: normal;margin-top:5px">{{deutscheBankEvent.name}}</span>
</div>
<!-- data-ng-repeat also possible-->
<div class="">
<div class="presse_content">
<Div style="color:white">{{deutscheBankEvent.name}}</div>
<ul class="liste_k">
<li ng-repeat="list in deutscheBankEvent.list">
{{list}}
</li>
</ul>
</div>
</div>
later down the code comes up a form to register to events. the form is hidden until user selects a place and date via select. this is triggered like so:
<span ng-show="myForm.locationDate.$valid">
my issue now is: this shows up all hidden form elements when one select is valid.
how can i set the scope to only this one changed?
Since ng-repeat creates a new scope, changing ng-show/ng-hide conditions to scope bound properties will work perfectly (example).

Resources