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.
Related
I am new to AngularJS and could really use some help. I have a button that's shown below that is part of a form. I need to show a modal when the form is submitted if the button is not clicked. How can I perform this check? I have tried several things with no luck.
<button ng-repeat="car in cars" btn-checkbox-false
class="btn btn-default btn-block text-left"
ng-click="AddRemoveCar(cars)">
<i ng-show="carInStock(cars)"
class="fa fa-check pull-right btn-success btn btn-xs" />
<i ng-show="!carInStock(cars)"
class="fa fa-plus pull-right btn-warning btn btn-xs" />
{{car.Model}}
</button>
Consider using the UI-Bootstrap uib-btn-checkbox directive for your Twitter Bootstrap checkboxes.
The uib-btn-checkbox directive, makes a group of Twitter Bootstrap buttons behave like a set of checkboxes.
Then your submit function can check the state of the model as bound with the ng-model directive.
For more information, see
UI-Bootstrap API Reference - Buttons
The DEMO1
angular.module('ui.bootstrap.demo', ['ngAnimate', 'ngSanitize', 'ui.bootstrap'])
.controller('ButtonsCtrl', function ($scope) {
$scope.checkModel = {
left: false,
middle: true,
right: false
};
$scope.$watchCollection('checkModel', function () {
$scope.checkResults = [];
angular.forEach($scope.checkModel, function (value, key) {
if (value) {
$scope.checkResults.push(key);
}
});
});
})
<script src="//unpkg.com/angular/angular.js"></script>
<script src="//unpkg.com/angular-animate/angular-animate.js"></script>
<script src="//unpkg.com/angular-sanitize/angular-sanitize.js"></script>
<script src="//unpkg.com/angular-ui-bootstrap/dist/ui-bootstrap-tpls.js"></script>
<link href="//unpkg.com/bootstrap#3/dist/css/bootstrap.min.css" rel="stylesheet">
<body ng-app="ui.bootstrap.demo" ng-controller="ButtonsCtrl">
<h4>Checkbox</h4>
<pre>Model: {{checkModel}}</pre>
<pre>Results: {{checkResults}}</pre>
<div class="btn-group">
<label class="btn btn-primary" ng-model="checkModel.left"
uib-btn-checkbox>Left</label>
<label class="btn btn-primary" ng-model="checkModel.middle"
uib-btn-checkbox>Middle</label>
<label class="btn btn-primary" ng-model="checkModel.right"
uib-btn-checkbox>Right</label>
</div>
</body>
I would be setting up some flag on the button click and check that value on form submit.
In my controller define a variable like btnClickedFlag = false;
In Button click function:
AddRemoveCar(cars) => {
this.btnClickedFlag = true;
}
Now on form submit , you can just check if btnClickedFlag is true if not display your modal/dialogue/overlay on screen.
How can I select a button based on its value and click on it (in Javascript)?
I already found it in JQuery:
$('input [type = button] [value = my task]');
My HTML Code for the Button is :
<button type="submit" value="My Task" id="button5b9f66b97cf47" class="green ">
<div class="button-container addHoverClick">
<div class="button-background">
<div class="buttonStart">
<div class="buttonEnd">
<div class="buttonMiddle"></div>
</div>
</div>
</div>
<div class="button-content">Lancer le pillage</div>
</div>
<script type="text/javascript" id="button5b9f66b97cf47_script">
jQuery(function() {
jQuery('button#button5b9f66b97cf47').click(function () {
jQuery(window).trigger('buttonClicked', [this, {"type":"submit","value":"My Task","name":"","id":"button5b9f66b97cf47","class":"green ","title":"","confirm":"","onclick":""}]);
});
});
</script>
What is the equivalent in JS and how may i click on it
(probably like this: buttonSelected.click(); ) .
And how do i run the javascript of the button clicked ?
Use querySelector to select it. Then click()
Your HTML has a button and not an input element so I changed the selector to match the HTML.
let button = document.querySelector('button[value="my task"]');
button.click();
<button type="submit" value="my task" id="button5b9f54e9ec4ad" class="green " onclick="alert('clicked')">
<div class="button-container addHoverClick">
<div class="button-background">
<div class="buttonStart">
<div class="buttonEnd">
<div class="buttonMiddle"></div>
</div>
</div>
</div>
<div class="button-content">Launch</div>
</div>
</button>
Otherwise, use this selector:
document.querySelector('input[type="button"][value="my task"]')
Note that if you have multiple buttons with the same value you'll need to use querySelectorAll and you'll get a list of all the buttons.
Then you can loop over them and click() them all.
Edit - new snippet after question edit
jQuery(function() {
jQuery('button#button5b9f66b97cf47').click(function() {alert('success')});
document.querySelector('button[value="My Task"]').click();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<button type="submit" value="My Task" id="button5b9f66b97cf47" class="green ">
<div class="button-container addHoverClick">
<div class="button-background">
<div class="buttonStart">
<div class="buttonEnd">
<div class="buttonMiddle"></div>
</div>
</div>
</div>
<div class="button-content">Lancer le pillage</div>
</div>
you can try:
var elements = document.querySelectorAll("input[type = button][value=something]");
note that querySelectorAll returns array so to get the element you should use indexing to index the first element of the returned array and then to click:
elements[0].click()
and to add a event listener u can do:
elements[0].addEventListener('click', function(event){
event.preventDefault()
//do anything after button is clicked
})
and don't forget to add onclick attribute to your button element in html to call the equivalent function in your javascript code with event object
I am not recommended this way because of excess your coding but as you mentioned, below are the equivalent way.
$(document).ready(function() {
var selectedbuttonValue = "2"; //change value here to find that button
var buttonList = document.getElementsByClassName("btn")
for (i = 0; i < buttonList.length; i++) {
var currentButtonValue = buttonList[i];
if (selectedbuttonValue == currentButtonValue.value) {
currentButtonValue.click();
}
}
});
function callMe(valuee) {
alert(valuee);
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.2.3/jquery.min.js"></script>
<input type="button" class="btn" value="1" onclick="callMe(1)" />
<input type="button" class="btn" value="2" onclick="callMe(2)" />
<input type="button" class="btn" value="3" onclick="callMe(3)" />
Using JavaScripts querySelector in similiar manner works in this case
document.querySelector('input[type="button"][value="my task" i]')
EDIT
You might save your selection in variable and attach eventListener to it. This would work as you desire.
Notice event.preventDefault() -function, if this would be part of form it would example prevent default from send action and you should trigger sending form manually. event-variable itselfs contains object about your click-event
var button = document.querySelector('input[type="button"][value="my task" i]')
button.addEventListener('click', function(event){
event.preventDefault() // Example if you want to prevent button default behaviour
// RUN YOUR CODE =>
console.log(123)
})
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>
I am searching how to show a div with AngularJS. I read some topic on StackOverflow but when I try to apply them, it doesn't works for my case...
This is my HTML code :
<div id="myPanel" ng-controller="controllerDependance" ng-show="myvalue" class="ng-cloak">
Blablabla
</div>
<div id="DivWhereIsMyButton" class="clearfix" ng-controller="controllerBubble">
Another div where is my button
<div id="containerButton" ng-controller="controllerDependance">
<button class="btn btn-danger btn-lg pull-right"
ng-click="showAlert()">View dependances
</button>
</div>
</div>
This is the controller :
d3DemoApp.controller('controllerBubble', function () {
});
d3DemoApp.controller('controllerDependance', function ($scope) {
$scope.myvalue = false;
$scope.showAlert = function(){
$scope.myvalue = true;
};
});
I initially thought, it is controllerOther take the hand and cancel the controllerDiv but even if I separate the both, it doesn't works. The problem is I am obligated to put the both in two differents controllers.
I have two controllers, controllerDependance and controllerBubble. My div to show is in the controllerDependance. My button is in a div controllerBubble and I can't move it. So I would like to wrap it in a div controllerDependance.
I make a Plunker to show you the problem : https://plnkr.co/edit/z1ORNRzHbr7EVQfqHn6z?p=preview
Any idea ?
Thanks.
Put the div you want to show and hide inside the controller. It needs to be within the scope of the controller, otherwise your controller function cant see it. Also, consider what you are trying to accomplish with the nested controllers, I often find them unnecessary.
<div id="divButton" class="clearfix" ng-controller="controllerOther">
<div id="buttonToShowDiv" ng-controller="controllerDiv">
<button class="btn btn-danger btn-lg pull-right" ng-click="showAlert()">Show my div</button>
<div id="myDiv"ng-show="myvalue" class="ng-cloak">
Blablabla
</div>
</div>
</div>
I notice in your original example you are declaring ng-controller="controllerDependance" twice in the DOM. I have never tried this before, but I can imagine this will cause problems. From the angular documentation on controllers
When a Controller is attached to the DOM via the ng-controller directive, Angular will instantiate a new Controller object, using the specified Controller's constructor function. A new child scope will be created and made available as an injectable parameter to the Controller's constructor function as $scope
I imagine that this is what is causing you problems. You have to have the div you want to show/hide within the scope of your controller.
I got your plunkr working, you can see my version here: https://plnkr.co/edit/NXbsVFMNHR8twtL8hoE2?p=preview
The problem was stemming from you declaring the same controller twice, and more importantly, the div to show/hide was using ng-show with a value from your mainController. But your div was outside that controller. So ng-show cant see the value. The div has to be withing the scope of the controller
You are using two different controllers which have different $scopes therefore their values are not connected! To show or hide a div is really simple in angular:
<div id="divButton" class="clearfix" ng-controller="myController">
<div id="buttonToShowDiv">
<button class="btn btn-danger btn-lg pull-right" ng-click="showAlert()">Show my div</button>
</div>
<div id="myDiv" ng-show="myvalue" class="ng-cloak">
Blablabla
</div>
</div>
And the script side just almost the same:
d3DemoApp.controller('myController', function AppCtrl ($scope) {
$scope.myvalue = false;
$scope.showAlert = function(){
$scope.myvalue = true;
};
});
Since you question was how to show elements using angular, I took the liberty of using just one controller.
Create a factory that will return an object and let your controllers work with a reference to the same object:
var d3DemoApp = angular.module('app', [])
d3DemoApp.factory('MyValue', function () {
return { value: false };
});
d3DemoApp.controller('controllerBubble', function ($scope, MyValue) {
$scope.myvalue = MyValue;
});
d3DemoApp.controller('controllerDependance', function ($scope, MyValue) {
$scope.myvalue = MyValue;
$scope.showAlert = function(){
$scope.myvalue.value = true;
};
});
<!DOCTYPE html>
<html>
<head>
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
</head>
<body>
<div ng-app="app">
<div ng-controller="controllerBubble" class="clearfix">
<div id="myPanel" ng-controller="controllerDependance" ng-show="myvalue.value" class="ng-cloak">
Blablabla
</div>
</div>
<div id="DivWhereIsMyButton" class="clearfix" ng-controller="controllerBubble">
Another div where is my button
<div id="containerButton" ng-controller="controllerDependance">
<button class="btn btn-danger btn-lg pull-right" ng-click="showAlert()">View dependances</button>
</div>
</div>
</div>
</body>
</html>
I am writing a Laravel 5 project with a comment section code below
#foreach($Comment as $Comment)
<div id="comment-{!! $Comment->comments_id !!}" class="comment-wrapper">
<div class="btn btn-lg btn-info btn-xs" class="show">Show</div>
<div class="btn btn-lg btn-success btn-xs" class="hide">Hide</div>
<div class="btn btn-lg btn-warning btn-xs" class="toggle">Toggle</div>
<div class="watch" class="jumbotron alert-info">
<ul class="list-group">
<li class="list-group-item list-group-item-success">{!! $Comment->author !!}</li>
<li class="list-group-item"> {!! $Comment->text !!}</li>
</ul>
#if ($Comment->author == Auth::user()->name)
<p>Delete</p>
#endif
<h6><small>CREATED ON: {!! $Comment->created_at !!}</small></h6>
</div>
</div>
#endforeach
and I have a javascript file which looks like this
$(document).ready(function () {
$('.show').click(function () {
$(this).closest('.comment-parent').find('.watch').show('slow');
});
$('.hide').click(function () {
$(this).closest('.comment-parent').find('.watch').hide('slow');
});
$('.toggle').click(function () {
$(this).closest('.comment-parent').find('.watch').toggle('slow');
});
});
The trouble is the toggle/hide javascript function only works on one set of buttons and hides all of the comments. I want to have the set of buttons that work for each comment individually. I've tried to increment the watch class and buttons div id by adding 1 and incrementing it for each comment but can't get it to work. Any help would be appreciated thanks.
You may try something like this:
$('#show').click(function () {
$(this).next('.watch').show('slow');
});
Try same approach for other methods, so only the next first div with class of watch will be acted and also, you could have wrapped each set in a single parent container using a unique id attribute in addition to a class, for better grouping. For example:
#foreach($Comment as $Comment)
<div id="comment-{{$comment->id}}" class="comment-wrapper">
<div class="btn btn-lg btn-info btn-xs show">Show</div>
<!-- More... -->
<div class="watch" class="jumbotron alert-info">
<!-- More... -->
</div>
</div>
#endforeach
This way, you could have done the jQuery slecting more specifically, for example:
$('#show').click(function () {
$(this).closest('.comment-parent').find('.watch').show('slow');
});
Update (Thanks to haakym for pointing me that): Also, an id must be unique so instead of using id='show' use it as a class and then use:
$('.show').click(function () {
$(this).closest('.comment-parent').find('.watch').show('slow');
});