I need to put a button in Ionic that stays activated after it's been pressed, and only deactivates after it's been pressed again.
There is a similar question but it only applies to icon buttons. (How to adding navigation bar button having ionic-on/ ionic-off functionality).
EDIT
I can't use a toggle button, it is required to be a regular looking buttom (in this case an Ionic button-outline) that stays active when pressed.
Here is some code:
<div class="botones">
<div class="row">
<div class="col">
<button class="button button-outline button-block button-positive">
Promociones
</button>
</div>
<div class="col">
<button class="button button-outline button-block button-energized" >
Aprobados
</button>
</div>
<div class="col">
<button class="button button-outline button-block button-assertive" >
Alerta
</button>
</div>
<div class="col">
<button class="button button-outline button-block button-balanced" >
ATM
</button>
</div>
</div>
</div>
As you can see is a simple horizontal array of buttons. They suppose to act as filters for a message inbox, so they have to stay pressed (one at the time at most) as the filter is active. Like a tab but not quite.
The main question is, how can I access the activated state of the button so I can mantain it activated.
In Ionic, you can add class 'active' to a .button, to make it look pressed/active.
And to make only one active at a time, you can do something like this:
angular.module('ionicApp', ['ionic'])
.controller('MainCtrl', function($scope) {
$scope.buttons = [
{icon: 'beer', text: 'Bars'},
{icon: 'wineglass', text: 'Wineries'},
{icon: 'coffee', text: 'Cafés'},
{icon: 'pizza', text: 'Pizzerias'},
];
$scope.activeButton = 0;
$scope.setActiveButton = function(index) {
$scope.activeButton = index;
};
});
<html ng-app="ionicApp">
<head>
<link href="//code.ionicframework.com/1.1.0/css/ionic.css" rel="stylesheet">
<script src="//code.ionicframework.com/1.1.0/js/ionic.bundle.js"></script>
</head>
<body ng-controller="MainCtrl">
<ion-content class="padding">
<div class="button-bar">
<button
ng-repeat="button in buttons"
ng-class="{'active': activeButton == $index}"
ng-click="setActiveButton($index)"
class="button icon ion-{{button.icon}}"
>
{{button.text}}
</button>
</div>
</ion-content>
</body>
</html>
Also, you can view a demo on Codepen.
You may find toggle button useful. Here's the official link to this example:
<ion-toggle ng-model="airplaneMode" toggle-class="toggle-calm">Airplane Mode</ion-toggle>
edit:
Here's a demo from Codepen
and the code pasted here:
angular.module('mySuperApp', ['ionic'])
.controller('MyCtrl',function($scope) {
});
<html ng-app="mySuperApp">
<head>
<meta charset="utf-8">
<title>
Toggle button
</title>
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no">
<link href="//code.ionicframework.com/nightly/css/ionic.css" rel="stylesheet">
<script src="//code.ionicframework.com/nightly/js/ionic.bundle.js"></script>
</head>
<body class="padding" ng-controller="MyCtrl">
<button class="button button-primary" ng-model="button" ng-click="button.clicked=!button.clicked" ng-class="button.clicked?'button-positive':'button-energized'">
Confirm
</button>
</body>
</html>
Related
I am working on custom textarea with highlighting options.
Now added h1-h4 & bold options.
Problem:
When I select the text and click on Heading1 button it style the whole row not selected text. When I click on Bold button it style only selected text.
I want to apply h1-h4 style only for selected text instead of whole row.
Here is my code:
<!DOCTYPE html>
<html lang="en">
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css">
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h2>Comment</h2>
<div class="panel panel-default">
<div class="panel-heading">
<button data-command="h1" class="btn btn-default btn-sm">Heading1</button>
<button data-command="h2" class="btn btn-default btn-sm">Heading2</button>
<button data-command="h3" class="btn btn-default btn-sm">Heading3</button>
<button data-command="h4" class="btn btn-default btn-sm">Heading4</button>
<button data-command="bold" class="btn btn-default btn-sm">Bold</button>
</div>
<div class="panel-body" contenteditable>Sample comment</div>
</div>
</div>
</body>
<script>
$(function() {
$(".btn").click(function() {
var command = $(this).data("command");
if (command == 'h1' || command == 'h2' || command == 'h3' || command == 'h4')
document.execCommand('formatBlock', false, '<' + command + '>');
else
document.execCommand(command);
})
})
</script>
</html>
I liked your question. I was not aware of this api. But please next time use ES6(it is everywhere now) and brackets for block expressions.
So from docs
Adds an HTML block-level element around the line containing the current selection, replacing the block element containing the line if one exists (in Firefox, is the exception — it will wrap any containing block element). Requires a tag-name string as a value argument. Virtually all block-level elements can be used.
But you can use insertHTML command.
<!DOCTYPE html />
<html lang="en">
<head>
<title>Bootstrap Example</title>
<meta charset="utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1" />
<link
rel="stylesheet"
href="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/css/bootstrap.min.css"
/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.4.0/js/bootstrap.min.js"></script>
</head>
<body>
<div class="container">
<h2>Comment</h2>
<div class="panel panel-default">
<div class="panel-heading">
<button data-command="h1" class="btn btn-default btn-sm">
Heading1
</button>
<button data-command="h2" class="btn btn-default btn-sm">
Heading2
</button>
<button data-command="h3" class="btn btn-default btn-sm">
Heading3
</button>
<button data-command="h4" class="btn btn-default btn-sm">
Heading4
</button>
<button data-command="bold" class="btn btn-default btn-sm">
Bold
</button>
</div>
<div class="panel-body" contenteditable>Sample comment</div>
</div>
</div>
</body>
<script>
$(function() {
$(".btn").click(function() {
var command = $(this).data("command");
if (
command == "h1" ||
command == "h2" ||
command == "h3" ||
command == "h4"
) {
const selection = window.getSelection();
document.execCommand(
"insertHTML",
false,
`<${command}>${selection}</${command}>`
);
} else {
document.execCommand(command);
}
});
});
</script>
</html>
Also do not forget to serialize you content.
http://play.ionic.io/app/81ff26fc9a28
<body ng-app="app">
<ion-pane ng-controller="myCtrl">
<ion-header-bar class="bar-stable">
</ion-header-bar>
<ion-content class="padding">
<input ng-model="myInput" style="border:1px solid #ddd;width:100%;padding:5px" type="text" placeholder="search"/>
<br>
<br>
<br>
<br>
<br>
<ion-footer-bar ng-show="!loading" align-title="center">
<div class="padding" style="position:absolute;bottom:0;width:100%">
<button ng-click="search(myInput)" class="button button-block button-positive footer-btn" type="submit">able to get myInput value if put within ion-content</button>
</div>
</ion-footer-bar>
</ion-content>
<ion-footer-bar ng-show="!loading" align-title="center">
<div class="padding" style="position:absolute;bottom:0;width:100%">
<button ng-click="search(myInput)" class="button button-block button-positive footer-btn" type="submit">cannot get myInput value here</button>
</div>
</ion-footer-bar>
</ion-pane>
</body>
How to solve this problem? for the styling sake, I have to put the click event and input field in 2 different directives, but that causes the problem I couldn't get the value of ng-model.
This is a case where using $scope is problematic. One possible solution is to use the ControllerAs syntax instead.
The ControllerAs syntax allows you to easily identify which controller a particular function or property belongs to, and forces the "always use a dot" rule for angular, avoiding any prototype inheritance issues.
This isn't the only way to solve the problem, but this is a solution that will help build a more robust application with fewer issues related to $scope.
http://play.ionic.io/app/df429e85d209
angular.module('app', ['ionic'])
.controller('myCtrl', function() {
var ctrl = this;
ctrl.search = function(value) {
alert(value);
};
});
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta name="viewport" content="initial-scale=1, maximum-scale=1, user-scalable=no, width=device-width">
<link href="https://code.ionicframework.com/1.0.0/css/ionic.min.css" rel="stylesheet">
<script src="https://code.ionicframework.com/1.0.0/js/ionic.bundle.js"></script>
</head>
<body ng-app="app">
<ion-pane ng-controller="myCtrl as ctrl">
<ion-header-bar class="bar-stable">
</ion-header-bar>
<ion-content class="padding">
<input ng-model="ctrl.myInput" style="border:1px solid #ddd;width:100%;padding:5px" type="text" placeholder="search" />
<br>
<br>
<br>
<br>
<br>
<ion-footer-bar ng-show="!loading" align-title="center">
<div class="padding" style="position:absolute;bottom:0;width:100%">
<button ng-click="ctrl.search(ctrl.myInput)" class="button button-block button-positive footer-btn" type="submit">able to get myInput value if put within ion-content</button>
</div>
</ion-footer-bar>
</ion-content>
<ion-footer-bar ng-show="!loading" align-title="center">
<div class="padding" style="position:absolute;bottom:0;width:100%">
<button ng-click="ctrl.search(ctrl.myInput)" class="button button-block button-positive footer-btn" type="submit">cannot get myInput value here</button>
</div>
</ion-footer-bar>
</ion-pane>
</body>
</html>
This is fixed code http://play.ionic.io/app/77035b24f58a
The issue is the $scope between two buttons are different, so the $scope.myInput value is not shared correctly.
One solution is add a $scope.model = {}; and refer to the model object like ng-model="model.myInput" and ng-click="search(model.myInput)". Then the inner scope will be access to the same model object.
This is the simplified code to demo this issue
var scope = {};
scope.myInput = '1';
var innerScope = Object.create(scope);
console.log(innerScope.myInput); // 1
innerScope.myInput = '2'; // myInput is 2 on innerScope
console.log(innerScope.myInput); // 2
console.log(scope.myInput); // 1 <-- but still 1 on scope
scope.model = {};
scope.model.myInput = '1';
console.log(innerScope.model.myInput); // 1
innerScope.model.myInput = '2'; //
console.log(innerScope.model.myInput); // 2
console.log(scope.model.myInput); // 2 <-- modify model.Input is visible on parent scope because they are modifying a same model object
I want to close the popover if the user click outside the popover. in the below code .tried it with few examples that were posted for clicking outside the popover but not working.
<!DOCTYPE html>
<html >
<head>
<meta charset="utf-8" />
<title>AngularJS Plunker</title>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.1/css/bootstrap.min.css" />
<script src="http://cdnjs.cloudflare.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="http://netdna.bootstrapcdn.com/bootstrap/3.1.1/js/bootstrap.min.js"></script>
<script src="https://code.angularjs.org/1.2.22/angular.js"></script>
</head>
<body ng-app="myApp">
<div class="example" ng-controller="MyCtrl">
<a class="btn btn-lg btn-success" href="javascript:;" popover ng-click="click()">popover</a>
<div style="display:none">
<div class="pop-content" id="val">
{{ myVar }}
<input type="button" />
</div>
</div>
<input ng-model="myVar">
</div>
</body>
</html>
<script>
var myApp = angular.module('myApp', []);
myApp.controller('MyCtrl', function ($scope) {
$scope.myVar = 3 + 4;
})
myApp.directive('popover', function ($compile) {
return {
link: function (scope, element, attrs) {
// define popover for this element
$(element).popover({
html: true,
placement: "top",
// grab popover content from the next element
content: $compile($(element).siblings(".pop-content").contents())(scope)
});
}
}
});
</script>
Seems like you ran into a Twitter bootstrap bug.. see this question here
you need to change you html to allow this feature.
<a class="btn btn-lg btn-success" href="javascript:;" popover ng-click="click()">popover</a>
to
<a popover class="btn btn-lg btn-success" href="javascript:;" tabindex="0" data-trigger="focus" >popover</a>
another problem is that you're not providing the content in JavaScript properly.
$(element).siblings("div").children(".pop-content").contents()
I did this inside you link function.
here is the plunk
Note: now you can't close it with the anchor itself..
-----------Update----------
To achieve this you'll have to do something like this data-trigger="click focus", but by using this I am running into an unusual bug. on first click the popover flick opens and closes immediately..
This is my CSS code. I want to set the display so that my text whats in the div shows up.
div.divi
{display: none}
This is my HTML code.
<!doctype html>
<html lang="nl">
<head>
<title>Over informatica en ik</title>
<meta charset="utf-8">
<link rel="stylesheet" href="opmaak.css">
</head>
<body>
<div class="divi">
<p class="groot">Informatica</p>
<p>hoi</p>
</div>
<button type="button"
onclick="document.getElementByClass('divi').style.display ='block'">
</button>
</body>
</html>
Try this:
div.divi {
display: none
}
<div class="divi">
<p class="groot">Informatica</p>
<p>hoi</p>
</div>
<button type="button" onclick="document.getElementsByClassName('divi')[0].style.display ='block'; this.style.display = 'none';">
</button>
Tell me if it needs improvement :)
Simply replace <div class="divi"> with <div id="divi"> and the CSS with div#divi{display: none}.
Or if you would prefer to keep divi as a class instead of an ID, you can update your code to the following:
<div class="divi">
<button id="div3">
<p class="groot">Informatica</p>
<p>hoi</p>
</div>
<button type="button" onclick="document.getElementsByClassName('divi')[0].style.display='block'">Text</button>
The main goal is to show different divs depending on which button I click, so they all start with the display style at "none" (except a default one called "atualizacoes"). And after I click a button ALL of the divs should be set to
display="none" and after that the one I associated that button with is set to display="block".
However something isn't right because when I click one of the buttons, the default div does disappear however nothing ever appears.
This is how I'm trying to accomplishing it:
In order:
snippet 1 - function I use inside my index.html to change all the
displays
snippet 2 - rule in my stylesheet
snippet 3 - parts of my index.html code (I didn't want to paste
EVERYTHING)
<script type="text/javascript">
function replace(show) {
document.getElementById('default').style.display="none";
document.getElementById('ecra').style.display="none";
document.getElementById(show).syle.display = "block";
}
</script>
.ecra
{
display: none;
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1">
<meta name="description" content="">
<meta name="author" content="">
<title>University Platform</title>
<!-- Bootstrap core CSS -->
<link href="bootstrap/css/bootstrap.css" rel="stylesheet">
<!-- Custom styles for this template -->
<link href="dashboard.css" rel="stylesheet">
<!-- jquery -->
<script src="assets/js/jquery.min.js"></script>
<script src="bootstrap/js/bootstrap.min.js"></script>
</head>
<body>
<!-- these are the buttons that are located on a sidebar -->
<div class="row">
<h3>Options</h3>
<button type="button" class="btn btn-default botao pull-left" onclick="replace('addestudante')">Adicionar Estudante</button>
</div>
<div class="row">
<button type="button" class="btn btn-default botao pull-left" onclick="replace('adduc')">Adicionar UC</button>
</div>
<!-- these are the divs I want to switch around -->
<div class="row" id='default'>
<p> Hello World </p>
</div>
<!-- in CSS I also made a rule that makes all "ecra" divs be invisible from the start-->
<div class="row ecra" id='addestudante'>
<button type="button" class="btn btn-default"> TEST 1</button>
</div>
<div class="row ecra" id='adduc'>
<button type="button" class="btn btn-default"> TEST 2</button>
</div>
</body>
Why is this function not working properly? Is there something wrong with my code?
There are a couple of issues with what you've written.
For one, you don't have any elements with ID "ecra" — what you want to do is affect all the elements that have the class "ecra". You can do this by looping or mapping over document.getElementsByClassName("ecra").
Secondly, you've misspelt style when you try to show the show element.
Try using this adapted function instead:
function replace(show) {
document.getElementById("default").style.display = "none";
Array.from(document.getElementsByClassName("ecra")).map(element => element.style.display = "none");
document.getElementById(show).style.display = "block";
}
By what I thought, you want to get elements by class name. They're ecra, so you can use querySelectorAll and do a loop for its length. I'll not use getElementsByClassName because it will make the line more longer and return an array.
function replace(show){
var q=document.querySelectorAll('.ecra'),
document.getElementById('default').style.display="none";
for(var i=0,l=q.length;i<l;i++){
!function(i){
q[i].style.display="none"
}(i)
}
document.querySelector('#'+show).style.display = "block"
}
I saw jQuery imported in your page. So I suggest to use jQuery.
<script type="text/javascript">
function replace(show) {
jQuery(function($){
$("#default").css({
"display" : "none"
});
$(".ecra").css({
"display" : "none"
});
$("#"+show).css({
"display" : "block"
});
});
}
</script>
Edited, missing characters.
JS corrected : http://jsfiddle.net/csfd8x35/
.ecra
{
display: none;
}
<!-- these are the buttons that are located on a sidebar -->
<div class="row">
<h3>Options</h3>
<button type="button" class="btn btn-default botao pull-left" onclick="replace1('addestudante')">Adicionar Estudante</button>
</div>
<div class="row">
<button type="button" class="btn btn-default botao pull-left" onclick="replace1('adduc')">Adicionar UC</button>
</div>
<!-- these are the divs I want to switch around -->
<div class="row" id='default'>
<p> Hello World </p>
</div>
<!-- in CSS I also made a rule that makes all "ecra" divs be invisible from the start-->
<div class="row ecra" id='addestudante'>
<button type="button" class="btn btn-default"> TEST 1</button>
</div>
<div class="row ecra" id='adduc'>
<button type="button" class="btn btn-default"> TEST 2</button>
</div>
<script>
function replace1(show) {
document.getElementById('default').style.display="none";
var allByClass = document.getElementsByClassName('ecra');
for (var i=0;i< allByClass.length; i++) {
allByClass[i].style.display = "none";
}
document.getElementById(show).style.display = "block";
}
</script>