Show/Hide(toggle) several blocks via Angular template engine - javascript

i need to show one and hide others.
in jquery i used 'this':
$('div').click(functiuon(){ this.show() });
maybe in Angular we can you use something like that?
<div class="toggle">
<span ng-click="this=!this ? true : false"></span><br/>
<span ng-if="this" >
111111111
</span>
</div>
<div class="toggle">
<span ng-click="this=!this ? true : false"></span><br/>
<span ng-if="this" >
2222222222222
</span>
</div>
etc this, this , this
I need to use only one varible for all blocks.

Any dom element interaction like clicking an element should be done within the directive and you can follow this to achieve what you want:
var app = angular.module('demoapp', []);
app.directive('toggleIt', function() {
return {
restrict: 'A',
link: function(scope, el, attrs) {
console.log(el.find('span'));
el.find('span').eq(0).on('click', function() {
el.find('span').eq(1).toggleClass('hide show');
});
}
};
});
.show{display:block;}
.hide{display:none;}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app='demoapp'>
<div data-toggle-it class="toggle">
<span>toggle1</span>
<br/>
<span class='spn show'>
111111111
</span>
</div>
<div data-toggle-it class="toggle">
<span>toggle2</span>
<br/>
<span class='spn hide'>
2222222222222
</span>
</div>
<div data-toggle-it class="toggle">
<span>toggle3</span>
<br/>
<span class='spn hide'>
3333333333333
</span>
</div>
</div>

You can use ng-hide for hiding an element on true or ng-show for showing an element on true:
<div class="toggle">
<span ng-click="pop1=!pop1 ? true : false"></span><br/>
<span ng-show="pop1" >
111111111
</span>
</div>
<div class="toggle">
<span ng-click="pop2=!pop2 ? true : false"></span><br/>
<span ng-show="pop2" >
2222222222222
</span>
</div>

You can use ng-if, ng-show, ng-hide, ng-class (in conjunction with css), and ng-switch.
ng-show, ng-hide and ng-if have kind of the same logic behind them (if the given variable is true/false, show/hide the following content). There are some performance differences between them, but this subject is out of scope.
Showing/hiding elements with ng-class is just a particular use case of it, but its achievable nonetheless.
To sum it up, ng-hide, ng-show, ng-if hide/show elements based on the truth evaluation of a given variable, while ng-class toggles a class, like
$('#someElement').toggleClass('randomClassName');
Example:
HTML
<div ng-app="exampleApp" ng-init="switchr1 = true; switchr2 = true; switchr3 = true; switchr4 = show; ">
<h2>ng-if</h2>
<div class="toggle">
<span ng-click="switchr1 = switchr1 ? false : true">click me</span><br/>
<span ng-if="switchr1" >
shown by ng-if
</span>
</div>
<h2>ng-show</h2>
<div class="toggle">
<span ng-click="switchr2 = switchr2 ? false : true">click me</span><br/>
<span ng-show="switchr2" >
shown by ng-show
</span>
</div>
<h2>ng-hide</h2>
which is the same thing as ng-show, but with reversed logic<br>
<div class="toggle">
<span ng-click="switchr3 = switchr3 ? false : true">click me</span><br/>
<span ng-hide="!switchr3" >
shown by ng-hide
</span>
</div>
<h2>ng-class</h2>
<div class="toggle">
<span ng-click="switchr4 = (switchr4=='show') ? 'hide' : 'show'">click me</span><br/>
<span ng-class="switchr4" >
hidden by ng-class
</span>
</div>
</div>
Notice, that you initiate switchr1, switchr2 and so on in the ng-init directive. You could have also done that in the js code, using $scope, but I did it this way for the sake of simplicity.
JS
var app = angular.module('exampleApp', []);
CSS
.hide {
display: none;
}
.show {
display: initial;
}
I also wrote some working code/full example for you:
http://codepen.io/VanTudor/pen/EKYZwM

Related

How can I conditionally display HTML in a button using AngularJS?

I would like for a certain button element to contain plain text by default, but then contain HTML based on some variable in my Angular scope. My goal is to have the button say "Save", but then become disabled and display a loading wheel when clicked (while awaiting a response from a long AJAX request). The problem is, Angular is displaying the literal text of my ternary operator in the button rather than the result of the expression.
Here's what my button looks like:
<button type="submit" ng-disabled="IsLoading" ng-click="OnClick()">
{{ IsLoading === false ? "Save" : "<i class='fa fa-spinner fa-pulse'></i>" }}
</button>
When I change the HTML to just some plain text (for instance, "Loading..."), then it works fine.
How can I get it to display the result of the expression rather than the text of the expression itself? Thanks.
Side note: I tried to get a demo up and running, but it seems that I can't figure out how to wire up the Angular properly using JSFiddle. This is not the purpose of my question, but I'd really like to know where I'm going wrong so I can successfully make simple Angular demos in the future. Any advice is appreciated.
Check out this fiddle
<div ng-app="myApp" ng-controller="LoadingController">
<div style="float: left;">
<button type="submit" ng-disabled="IsLoading" ng-click="OnClick()">
<span ng-if="!IsLoading">
Save
</span>
<span ng-if="IsLoading">
<i class="fa fa-spinner fa-pulse"></i>
</span>
</button>
</div>
<div style="float: left;">
<button type="submit" ng-disabled="IsLoading" ng-click="OnClick()">
<span ng-if="!IsLoading">
Save
</span>
<span ng-if="IsLoading">
Loading...
</span>
</button>
</div>
</div>
js
angular.module("myApp",[]).controller('LoadingController', function LoadingController ($scope) {
$scope.IsLoading = false;
$scope.OnClick = function() {
$scope.IsLoading = true;
window.setTimeout(function() {
$scope.IsLoading = false;
}, 1000);
};
});
note:Angular 1.1.5 added a ternary operator support, and your fiddle pointing to older version, that's why its not working
I will suggest to google about the following 3 things which will serve your needs in any way. You will easily find it
ng-if
ng-show
ng-hide
ng-hide & ng-show will just play around by switching the css display property while ng-if will only add the html in case required condition equals to true.
<input type="checkbox" ng-model="flag" ng-init="flag= true">
<div ng-if="flag">
<h1>Welcome</h1>
<p>Hello mate.</p>
</div>
I think you are trying to achieve this
All codes are in that link. Posted important part code
<button type="submit" ng-disabled="IsLoading" ng-click="OnClick()">
<span ng-hide="IsLoading">Save</span>
<span ng-show="IsLoading"><i class='fa fa-spinner fa-pulse'></i </span>
</button>
WORKING DEMO
Try this:
https://plnkr.co/edit/rguvZ2Xs4lwl4QhA9Cv0
<script>
var app = angular.module('plunker', []);
app.controller('MainCtrl', function($scope, $timeout) {
$scope.isLoading = false;
$scope.click = function() {
$scope.isLoading = true;
$timeout(function() {
$scope.isLoading = false;
}, 2000);
}
});
</script>
<style>
.loadingButton.loading span {
display: none;
}
.loadingButton.loading i {
display: block;
}
.loadingButton i {
display: none;
}
</style>
<button type="submit" ng-disabled="isLoading" ng-click="click()" class="loadingButton" ng-class="{'loading': isLoading}">
<span>Save</span>
<i class='fa fa-spinner fa-pulse'>icon</i>
</button>
The "Angular way" would by this
<button type="submit" ng-disabled="IsLoading" ng-click="OnClick()">
<span ng-hide="IsLoading">Save</span>
<i ng-show="IsLoading" class='fa fa-spinner fa-pulse'></i>
</button>
But you need to actually load Angular.js in your jsfiddle, i.e. <script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.5/angular.js"></script>
Working Plunker: http://plnkr.co/edit/ELYDsfIsbeo7sSvub6Nx?p=preview
Wrap your i element in an div with the ng-show or ng-hide element and then apply your expression to the value of either of those two directives.
Check this jsfiddle , Its a working example of what you are asking for
Updating a little code :
<div ng-app ng-controller="Controller">
<div style="float: left;">
<button type="submit" ng-disabled="IsLoading" ng-click="OnClick()">
{{ IsLoading === false ? "Save" : "<i class='fa fa-spinner fa-pulse'></i>" }}
</button>
</div>
<div style="float: left;">
<button type="submit" ng-disabled="IsLoading" ng-click="OnClick()">
{{ IsLoading === false ? "Save" : "Loading..." }}
</button>
</div>
</div>

Add class based on a condiiton in angularjs?

I want to add classes based on a condition in angularJs, I am following below method and it is working fine, Is there any best practice?
<div ng-if="client.status != 2" class="list-primary">
<span class="pull-right amount">{{client.receivables|number:2}}</span>
<div class="name">{{client.name}}</div>
</div>
<div ng-if="client.status == 2" class="list-primary text-muted">
<span class="pull-right amount">{{client.receivables|number:2}}</span>
<div class="name">{{client.name}}</div>
</div>
You can use ng-class for this:
<!-- apply class 'text-muted' when client.status == 2 -->
<div class="list-primary" ng-class="{ 'text-muted': client.status == 2 }">
<span class="pull-right amount">{{client.receivables|number:2}}</span>
<div class="name">{{client.name}}</div>
</div>
In angular 1.1.5+ you can use javascript ternary operator.
<div ng-class="client.status == 2 ? 'text-muted' : 'other-class'" class="list-primary ">
<span class="pull-right amount">{{client.receivables|number:2}}</span>
<div class="name">{{client.name}}</div>
</div>
I hope this helps
Have a look at ng-class which is provided in AngularJS. Documentation here:
https://docs.angularjs.org/api/ng/directive/ngClass

How to ng-style one element it's $index created by ng-repeat?

I have 2 directives: wa-hotspots & wa-tooltips.
On ng-mouseover of wa-hotspots it takes that $index of wa-hotspot and sets the visibility and position of wa-tooltip via ng-class:on and ng-style="tooltipCoords" by matching indexes.
Note: Since wa-hotspots & wa-tooltips share the same collection page.hotspots and therefore they share teh same index via ng-repeat
Problem:
When you hover over wa-hotspots it sets the ng-style position to ALL of the elements in wa-tooltips. I only want it ot set the proper matching index. Since the visiblity is controlled by ng-class, This doesn't really matter but it seems like it's extra overhead that could be avoid.
Therefore:
Question:
How can I make sure that my ng-style isn't styling all the wa-tooltips on hover of wa-hotspots? But rather, style only the tooltip that matches the proper shared index?
<ul id="wa-page-{{page.pageindex}}" class="wa-page-inner" ng-mouseleave="pageLeave()">
<li wa-hotspots
<map name="wa-page-hotspot-{{page.pageindex}}">
<area ng-repeat="hotspot in page.hotspots"
class="page-hotspot"
shape="{{hotspot.areashape}}"
coords="{{hotspot.coordinatetag_scaled}}"
ng-mouseover="showTooltip($index, hotspot.coordinatetag_scaled)"
ng-mouseout="hideTooltip()">
</map>
</li>
<li class="tooltip-wrapper">
<ul class="tooltip">
<li wa-tooltips
ng-repeat="hotspot in page.hotspots"
ng-class="{on: hovered.index == $index}"
ng-mouseover="hovered.active == true"
ng-mouseout="hovered.active == false"
ng-style="tooltipCoords" hotspot="hotspot">
</li>
</ul>
</li>
</ul>
tooltip:
You need to make it per item like in your case - hotspot.tooltipCoords then set that variable by index.
you can do the check inside the expression function.
Heres a fiddle
<div ng-controller="MyCtrl">
<div ng-repeat="item in items" ng-style="isChecked($index)">
name: {{item.name}}, {{item.title}}
<input type="checkbox" ng-model="item.checked" />
</div>
</div>
...
$scope.isChecked = function($index){
var color = $scope.items[$index].checked ? 'red' : 'blue';
return {color:color};
}
Instead of
ng-mouseover="hovered.active == true"
ng-mouseout="hovered.active == false"
use
ng-mouseover="hotspot.class== 'active'"
ng-mouseout="hotspot.class== ''"
and after that you can use hotspot.class in ng-class ie:
ng-class="hotspot.class"
Please see demo below:
var app = angular.module('app', []);
app.controller('homeCtrl', function($scope) {
$scope.items = [{
id: 1
}, {
id: 2
}, {
id: 3
}, {
id: 4
}]
});
.red {
background-color: yellow;
}
p {
background-color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="app">
<div ng-controller="homeCtrl">
<p ng-repeat="i in items" ng-mouseover="i.class='red'" ng-class="i.class" ng-mouseout="i.class = ''">{{i.id}}</p>
</div>
</div>
Use the below one
<div class="col-md-4 col-xs-12 col-lg-4" ng-repeat="obj in items">
<button type="button" class="btn btn-sm pull-right" ng-class="obj.class" ng-click="obj.class='test'" >
Write a new class "test". Instead of click you can use the same in ngmouseover

AngularJS ng-switch-trigger within its own ng-switch-wrapper

I am trying to switch 2 buttons which are their own switch-triggers. For better understanding:
<span ng-switch on="patientSwitch">
<span ng-switch-when="edit">
<button ng-click="patientSwitch='save'">save</button>
</span>
<span ng-switch-when="save">
<button ng-click="patientSwitch"='edit'">edit</button>
</span>
</span>
Here is some jsFiddle: http://jsfiddle.net/g7vKz/
Use an object instead:
myApp.controller("PatientCtrl", function($scope) {
$scope.viewModel = { patientSwitch: "edit" };
});
And:
<span ng-switch on="viewModel.patientSwitch">
<span ng-switch-when="edit">
<button ng-click="viewModel.patientSwitch='save'">save</button>
</span>
<span ng-switch-when="save">
<button ng-click="viewModel.patientSwitch='edit'">edit</button>
</span>
</span>
Demo: http://jsfiddle.net/M7EX2/
ngSwitch creates a new scope, which means unless you use an object you will get this problem due to how prototypal inheritance works in JavaScript.
Very good post on the subject can be found here.

Ng-repeat, first item with different directive

I got the following code:
<div ng-repeat="i in placeholders" square class="set-holder {{i.class}}" droppable="{{i.type}}"></div>
How I make the first item has the directive bigsquare, while the others have just square.
I've tried:
<div ng-repeat="i in placeholders" {{= $first ? 'big' : ''}}square class="set-holder {{i.class}}" droppable="{{i.type}}"></div>
but sadly I the result is:
<div ng-repeat="i in placeholders" {{= $first ? 'big' : ''}}square class="set-holder test" droppable="3"></div>
a.k.a. the binding don't get compiled.
You can use ng-repeat-start and ng-repeat-end as follows:
angular.module('example', [])
.controller('ctrl', function Ctrl($scope) {
$scope.items = [1, 2, 3];
})
.directive('big', function() {
return {
restrict: 'A',
link: function(scope, element, attrs) {
element.css('font-size', '30px');
}
};
});
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<div ng-app="example" ng-controller="ctrl">
<div ng-repeat-start="item in items" ng-if="$first" big>
big item {{item}}
</div>
<div ng-repeat-end ng-if="!$first">
item {{item}}
</div>
</div>
The documentation can be found under ng-repeat.
See this fiddle http://jsfiddle.net/nicolasmoise/xLfmK/2/.
You can create one directive to which you pass a condition. Depending on that condition it will either display the square or the big-square as such.
<div ng-repeat="repeat in repeater" condition="$first" square></div>
Note
If you don't want to alter the directives you're already made, you can always have square be a master directive that calls the other two.
If you don't mind using another <div> inside of your <li>, you should be able to get away with doing conditional blocks of <div> using ng-if="$index == ??".
Maybe something like this:
<div ng-repeat="i in placeholders">
<div bigsquare class="set-holder {{i.class}}" droppable="{{i.type}}" ng-if="$index == 0">
...
</div>
<div mediumsquare class="set-holder {{i.class}}" droppable="{{i.type}}" ng-if="$index == 1">
...
</div>
<div square class="set-holder {{i.class}}" droppable="{{i.type}}" ng-if="$index > 1">
...
</div>
</div>
It's a little more verbose, but it nicely separates out the templates so that you can have them pretty independent of each other.
<!-- Here is a code sample which I used in one of my angularjs ionic apps. -->
<!-- Regular ng-repeat -->
<!-- ng-if="$first" to determine <input focus-input> or not -->
<ion-item class="item item-input item-stacked-label" ng-repeat="input in template.inputs">
<label class="input-label bh-dark" for="{{input.id}}">{{input.title}}</label>
<div class="clearfix">
<div class="bh-left">
<input ng-if="$first" focus-input id="{{input.id}}" type="{{input.type}}" placeholder="{{input.choices[0]}}" ng-model="input.answer">
<input ng-if="!$first" id="{{input.id}}" type="{{input.type}}" placeholder="{{input.choices[0]}}" ng-model="input.answer">
</div>
<div class="bh-right">
<i class="icon ion-ios-close-empty bh-icon-clear" ng-click="clearField(input.id)" ng-show="input.answer"></i>
</div>
</div>
</ion-item>

Categories

Resources