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

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>

Related

ng-show in angularjs not working on span

I'm facing a problem with ng-show in Angularjs. I have a textbox where a user can enter the host name of a server. On entering this information, the hostname of the server gets sent to the backend system which verifies if the server exists or not. I am currently displaying a loading icon in my textbox using bootstrap, font awesome and angularjs. When I receive a response from the server, I change the isLoaded variable to true and I expect the loading icon to stop showing. However, this does not happen. Whatever state the icon is first set to, it never changes after that.
Here's the simplified version of my problem. Plunker Link Here
HTML
<form>
<div class="form-group has-feedback">
<label for="server">Server:</label>
<input type="text" id="server" class="form-control" placeholder="server host name">
<span ng-show="{{testVm.state}}" class="fa fa-spinner fa-spin form-control-feedback" aria-hidden="true"></span>
<button class="btn btn-primary" ng-click="testVm.turnOn()">Activate</button>
<button class="btn btn-primary" ng-click="testVm.turnOff()">Deactivate</button>
</div>
</form>
Angular Code:
angular
.module('test',[])
.controller('TestController',TestController);
function TestController() {
var testVm = this;
testVm.turnOn = turnOn;
testVm.turnOff = turnOff;
testVm.state = false;
function turnOn() {
testVm.state = true;
}
function turnOff() {
testVm.state = false;
}
Any help is appreciated. Thanks.
You are using ng-show the wrong way. You don't need the double curly braces, because you're not evaluating the string value of the variable.
<span ng-show="testVm.state" class="fa fa-spinner fa-spin form-control-feedback" aria-hidden="true"></span>
Fixed plunker

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

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

How to change html inside a span

I want to change the content of a span in my form
HTML:
<form action="javascript:submit()" id="form" class="panel_frame">
<label>Origin:</label>
<div class="input-group" id="input-group">
<input type="text" id="origin" name="origin" class="form-control">
<span class="input-group-btn">
<button id="btn-default" class="btn btn-default" type="button">
<span class="glyphicon glyphicon-pushpin" aria-hidden="true"></span>
</button>
</span>
</div>
What I want change is che content of <span class="input-group-btn"> with
<button id="btn-default" class="btn btn-default" type="button">
<span class="glyphicon glyphicon-remove" aria-hidden="true"></span>
</button>
So what change is: the icon pushpin to remove and the action useCurrentPosition to clearPosition.
I' using jquery and despite I've read other answer about similar question on Stack like: How can I change the text inside my <span> with jQuery? and how to set a value for a span using JQuery I haven't solved the issue.
I tried:
$("#input-group span").html('
<button id="btn-default" class="btn btn-default" type="button" onclick="br_bus.useCurrentPosition()">
<span class="glyphicon glyphicon-pushpin" aria-hidden="true"></span>
</button>
');
,giving an id to the span and also modify the full div, but none solved my problem.
What am I missing?
Here's a way to overcome the problem of changing the onclick attribute, which is bad practice, without storing a Global var, and using jQuery delegation (learn to use it, it's really good):
$(document).on('click','.btn', positionChange); // Give that button an id on his own and replace '.btn' with '#newId'
// Not using an anonymous function makes it easire to Debug
function positionChange(){
var $btn = $(this), // Caching jQuery elements is good practice
$span = $btn.find('span'), // Just caching
pushpinApplied = $span.hasClass('glyphicon-pushpin'); // Check which icon is applied
( pushpinApplied ) ? useCurrentPosition() : clearPosition();
$span.toggleClass( 'glyphicon-pushpin glyphicon-remove' );
}
Rather than changing the function called in the onclick attribute I suggest having a flag in one function to define the logic it should follow.
For example:
function positionChange(this){
var $this = $(this);
if(!$this.data("currentpositionused")){
//useCurrentPosition() code here
$this.data("currentpositionused", true);
}
else {
//clearPosition() code here
$this.data("currentpositionused", false);
}
Then change your HTML to:
<button class="btn btn-default" type="button" onclick="positionChange(this)">
If you want to change only the onclick attribute of the button inside the particular span you can use the following in your script.,
$(document).ready(function(){
$("span.input-group-btn button").attr("onclick","clearPosition()");
});
EDIT
$(document).ready(function(){
$("span.input-group-btn button").attr("onclick","clearPosition()");
$("span.input-group-btn button span").attr("class","Your_class");
});
And also learn about how to change/add/remove attribute values....
Try this:
$("span.input-group-btn").html('<button class="btn btn-default" type="button" onclick="clearPosition()">
<span class="glyphicon glyphicon-pushpin" aria-hidden="true"></span>
</button>');
Is it like This ?
how to change onclick event with jquery?
$("#id").attr("onclick","new_function_name()");
jquery change class name
$("#td_id").attr('class', 'newClass');
If you want to add a class, use .addclass() instead, like this:
$("#td_id").addClass('newClass');

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.

AngularJS toggle button

I am trying to create a toggle button in Angular. What I have so far is:
<div class="btn-group">
<a class="btn btn-primary pull-right"
ng-click="toggleArchive(true)"
ng-show="!patient.archived">Archive patient</a>
<a class="btn btn-danger pull-right"
ng-click="toggleArchive(false)"
ng-show="patient.archived">Unarchive patient</a>
.... some other buttons ....
</div>
Basically I achieve toggling, by having TWO buttons, and toggling between them. This is causing issues because the ng-hide just adds a display:none style to the button when it's hidden, which is causing me styling issues. Ideally I want to have ONE button, that has it's text, class and function call changed depending on the state of patient.archived.
What's a clean way to achieve this?
You should use ng-class to toggle between classes and bind the text with a regular Angular expression. Also, if your function toggleArchive only toggle the value, you can remove it and toggle the value from an Angular expression:
<a class="btn pull-right"
ng-class="{true: 'btn-primary', false: 'btn-danger'}[!patient.archived]"
ng-click="patient.archived = !patient.archived">
{{!patient.archived && 'Archive' || 'Unarchive'}} patient
</a>
for any other weary traveller...
you could simply have used ng-if. ng-if completely excludes the element from the DOM if false, so you'd have no issues with styles when not displayed. Also there is not really a need for the button group you could just change the text of the button
Something like this:
<button class="btn btn-primary pull-right"
ng-click="toggleArchive(true)"
ng-if="!patient.archived">Archive patient</button>
<button class="btn btn-danger pull-right"
ng-click="toggleArchive(false)"
ng-if="patient.archived">Unarchive patient</button>
It might help you:
<html>
<head>
<script src="js/angular.js"></script>
<script src="js/app.js"></script>
<link rel="stylesheet" href="css/bootstrap.css">
</head>
<body ng-app>
<div ng-controller="MyCtrl">
<button ng-click="toggle()">Toggle</button>
<p ng-show="visible">Hello World!</p>
</div>
</body>
</html>
function MyCtrl($scope) {
$scope.visible = true;
$scope.toggle = function() {
$scope.visible = !$scope.visible;
};
}
This may Help:
<!-- Include Bootstrap-->
<script src="//angular-ui.github.io/bootstrap/ui-bootstrap-tpls-0.13.3.js"></script>
<!-- Code -->
Click here to <strong>Toggle (show/hide)</strong> description
<input type="checkbox" class="toggle-button"
ng-model="patient.archived">
Then style the checkbox like a button.
if the toggle needs to do more things, add the following to your patient class:
class Patient {
constructor() {
this.archived = false;
}
...
get angularArchived() {
return this.archived;
}
set angularArchived(value) {
if (value !== this.archived) {
toggleArchived(value);
}
this.archived = value;
}
}
then use
<input type="checkbox" class="toggle-button"
ng-model="patient.angularArchived">
This is the simplest answer I've found. I haven't tried it with animations because I just use it for quick setup.
<a ng-click="scopeVar=scopeVar!=true">toggle</a>
<div ng-show="scopeVar">show stuff</div>
with scopeVar=scopeVar!=true undefined becomes true.

Categories

Resources