I am new to Angular and installed ng-sidebar component through NPM, I have designed my sidebar:
component.html:
<ng-sidebar-container>
<ng-sidebar
[(opened)]="_opened"
mode="push"
autoCollapseWidth=500>
<div>
<!-- Sidebar-content goes here -->
</div>
</ng-sidebar>
<div ng-sidebar-content>
<router-outlet></router-outlet>
<a id="show-sidebar" class="btn btn-sm btn-dark" href="#" (click)="_toggleSidebar()">
<i class="fas fa-bars"></i>
</a>
</div>
</ng-sidebar-container>
Now, I have a toggle button above with id #show-sidebar, I want to apply left: 300px; on it when sidebar opened, for that I looked up the console and found an attribute on ng-sidebar tag as ng-reflect-opened, then I wrote the following style:
ng-sidebar[ng-reflect-opened=true] + div[_ngcontent-oer-c1] > div[_ngcontent-ocs-c0] a#show-sidebar {
left: 300px;
}
But it's not working! Any suggestions?
Note: Sidebar is toggling just to add style to toggle button.
This can be done by class binding, just make a class in your CSS as:
.toggled {
left: 300px;
}
As you have a property _opened in your .ts file which is Boolean so just add this to your desired element: [ngClass]="{toggled : _opened}".
Hope it will help :)
Related
I have a button that I want to be able to toggle a class on a div to hide and show the div how would I do that in Angular?
HTML
<div id="chatsidebar">
<app-chatsidebar></app-chatsidebar>
</div>
<div>
<button type="button" id="sidebarCollapse" class="btn btn-info" (click)="togglesideBar()">
<i class="glyphicon glyphicon-align-right"></i>
Toggle Sidebar
</button>
</div>
I want to add the class "active" onto the #chatsidebar div
app.component.ts
togglesideBar() {
}
Thanks
I'm answering this part of your question:
I want to add the class "active" onto the #chatsidebar div
To do it, you can use NgClass. NgClass allows you to add or remove any class to or from an element based on the given condition. Your code will looks something like this:
HTML
<div id="chatsidebar" [ngClass]="{'active': isSideBarActive}"> <!-- this ngClass will add or remove `active` class based on the `isSideBarActive` value -->
<app-chatsidebar></app-chatsidebar>
</div>
<div>
<button type="button" id="sidebarCollapse" class="btn btn-info" (click)="togglesideBar()">
<i class="glyphicon glyphicon-align-right"></i>
Toggle Sidebar
</button>
</div>
Component
isSideBarActive: boolean = true; // initial value can be set to either `false` or `true`, depends on our need
togglesideBar() {
this.isSideBarActive = !this.isSideBarActive;
}
HTML
<div id="chatsidebar" *ngIf="status">
<app-chatsidebar></app-chatsidebar>
</div>
<div>
<button type="button" id="sidebarCollapse" class="btn btn-info" (click)="togglesideBar()">
<i class="glyphicon glyphicon-align-right"></i>
Toggle Sidebar
</button>
</div>
app.component.ts:
status:boolean=true;
togglesideBar() {
if(this.status == true) this.status=false;
else this.status = true;
}
Demo:
https://plnkr.co/edit/fNoXWhUhMaUoeMihbGYd?p=preview
you can try below.
<div id="chatsidebar" class="{{activeClass}}"> ... </div>
and on your component define a property and set the class value on toggle function
// On Component
activeClass : string = "";
...
togglesideBar() {
this.activeClass = 'active'
}
it shall work, but may not the ideal solution.
Assuming you have a class named hide:
<div [class.hide]="hide">
<app-chatsidebar></app-chatsidebar>
</div>
<div>
<button type="button" class="btn btn-info" (click)="togglesideBar()">
<i class="glyphicon glyphicon-align-right"></i>
Toggle Sidebar
</button>
</div>
togglesideBar() { this.hide = !this.hide; }
This will hide the element in question, while leaving it in the DOM. The other solutions using *ngIf will add and remove the element to and from the DOM. There are subtle reasons in specific cases to prefer one over the other, well described in the on-line documentation you have already read. In this case, it doesn't really matter.
The [class.className]=boolean format is just one of several ways to control classes in Angular. For instance, you could also have said:
[ngClass]="{'hide': hide}"
This is slightly more flexible because you can add/remove multiple classes at once.
Since you are using glyphicons, you are probably using Bootstrap, so you most likely already have the hide class defined.
As an aside, you rarely need IDs, and using them is pretty much of an anti-pattern in Angular.
Take a variable in your component something like
isShowChatSidebar:boolean=true;
then modify your method and html
togglesideBar() {
this.isShowChatSidebar=!this.isShowChatSidebar
}
<div id="chatsidebar" [ngClass]="{'active': isShowChatSidebar}">>
<app-chatsidebar></app-chatsidebar>
</div>
How to show / hide edit icon on mouseover and mouseout on particular text.
Here is my html code snippet
<ul>
<li>
<a id="pop" href="javascript:;;" data-content="test Desc" data-id="123">
<span class="testNameInfo">Test</span>
</a>
<div class="pull-right icons-align">
<i class="fa fa-pencil"></i>..
<i class="fa fa-plus"></i>
<i class="fa fa-times"></i>
</div>
</li>
</ul>
when page loads the fa-pencil icon is in hide state. When i mouse over on text, it should show fa-pencil icon. Remaining icons (add and delete) are always in show state.
Here is my javascript to hide the fa-pencil icon
$("a.editInline").css("display","none");
Am using backbone and marionette js frameworks, so i need to register the events in view.
Please let me know what is the best way to get out from my issue.
You can do as below:
$('.testNameInfo').on('mouseover mouseout',function(){
$(this).closest('li').find('.editInline').toggle();
//find the closest li and find its children with class editInLine and
//toggle its display using 'toggle()'
});
UPDATE
DEMO
#JamieBarker made his point which is valid here so I would suggest to try below code instead
$("a.editInline").css("display","none");
$('li').on('mouseover mouseout',function(){
$(this).find('.editInline').toggle();
//find its children with class .editInLine and
//toggle its display using 'toggle()'
});
Better to use CSS than JavaScript if you can:
a.editInline {
display:none;
}
li:hover a.editInline {
display:inline-block;
}
UPDATE
Performance/Simplicity wise I'd advise going with the CSS solution provided. If all else you can use then JS solution.
Optional CSS Solution
.editInline {
display: none;
}
#pop:hover .icons-align .editInline {
display: inline-block;
}
JS Solution
$(function() {
$(".editInline").hide(); // Use this if CSS is not wanted
$("#pop").hover(function() {
$(".editInline").show();
}, function() {
$(".editInline").hide();
});
});
I have a simple ng-click in the nav bar and it doesn't work. I've placed the html template inside of a directive but the alert does not appear. There are no other issues in my console. I'm stumped as to why this doesn't work.
<signed-in-header></signed-in-header>
My directive as a whole.
angular.module('CoolSite.user')
.directive('signedInHeader', signedInHeader)
function signedInHeader() {
return {
template: template,
link: link,
scope: { }
}
function link(scope, elem, attrs) {
scope.alert = function() {console.log("ALERTED")}
}
function template() {
return [
'<ion-nav-bar class="bar-light" align-title="center">',
'<ion-nav-buttons side="left">',
'<img ng-click="alert(123)" height="30" src="/img/logo-full.png">',
'</ion-nav-buttons>',
'<ion-nav-buttons side="right">',
'<div ui-sref="tab.cart">',
'<i class="icon ion-ios-cart-outline"></i>',
'<div id="cartCount" class="assertive">1</div>',
'</div>',
'</ion-nav-buttons>',
'</ion-nav-bar>'
].join("");
}
}
Plunker here.
You just need to add the button class to your image. You can add button-clear so that the button border is not added.
<img class="button button-clear" ng-click="alert(123)" src="https://cdn1.iconfinder.com/data/icons/hawcons/32/700015-icon-27-one-finger-click-32.png" />
Working Plunker
To clarify, everyone was correct on some level:
icycool was right in that the actual issue is the z-index. The ionic button class adds z-index: 1.
Krytic points out that without the ionic css linked it will work (because the elements then just default to relative position and the button isn't obscured).
aorfevre's suggestion to use a link worked not because it was an anchor tag, but because the link had the button class applied.
I think you can't specify a directive using id?
Angular doc says:
The restrict option is typically set to:
'A' - only matches attribute name
'E' - only matches element name
'C' - only matches class name
Maybe you can try adding it as an attribute?
<ion-nav-bar signed-in-header id="signedInHeader" class="bar-light" align-title="center">
I have slightly updated your case with a templateUrl which is, in my opinion, much more readable.
http://plnkr.co/edit/8CHdeRmDtG52PgvAbucG?p=preview
Template here :
<ion-nav-bar id="signedInHeader" class="bar-light" align-title="center">
<ion-nav-buttons side="left">
<a class="button button-icon button-clear " ng-click="test()">CLICK
</a>
</ion-nav-buttons>
</ion-nav-bar>
I have created a test function that is added to your directive link.
scope.test= function(){
alert("TEST");
}
What you have to remember is that ng-click will look for a function bound to the current $scope, so if you do
ng-click="alert(123)"
it is looking for a function $scope.alert and will not find it. It does not look in the window object to find it.
Ionics CSS comes with this rule:
img {
-webkit-user-drag: none;
}
Removing this from ionic.css or setting it to auto should solve this.
Update:
this doesn't solve the issue for the OP.
But using his plunkr, removing the ionic.css from the document fixes the issue. Just as a hint, the answer is somewhere out there ;)
Some how the generated ionic code has it's title blocking its own button.
<ion-nav-bar id="signedInHeader" class="bar-light nav-bar-container" align-title="center" nav-bar-transition="ios">
<ion-nav-buttons side="left" class="hide"></ion-nav-buttons>
<ion-nav-buttons side="right" class="hide"></ion-nav-buttons>
<div class="nav-bar-block" nav-bar="cached">
...
</div>
<div class="nav-bar-block" nav-bar="active">
<ion-header-bar class="bar-light bar bar-header disable-user-behavior" align-title="center">
<div class="buttons buttons-left header-item">
<span class="left-buttons">
<div ng-click="alert(123)">click me</div>
</span>
</div>
<div class="title title-center header-item"></div> <!-- this line -->
<div class="buttons buttons-right header-item">
<span class="right-buttons">
<div>
<i class="icon ion-ios-cart-outline"></i>
<div id="cartCount" class="assertive">1</div>
</div>
</span>
</div>
</ion-header-bar>
</div>
</ion-nav-bar>
The title is having a css in ionic.css
.bar .title {
position: absolute;
top: 0;
right: 0;
left: 0;
z-index: 0;
...
}
In CSS rules position:absolute items will be placed on top of normal flow items.
There might be a way in ionic coding style that fixes this issue but I can't find it.
So I fixed it by raising the buttons and make it covers the title again
.bar .buttons-left {
position: absolute;
z-index: 1;
}
Note that after this fix the left buttons will cover the title if title text is long enough to go under it, or the title text is aligned left.
I have an html element which is using bootstrap tooltip to show a title when hovering over it. However, when you click this element I'm changing the tooltip, but the new tooltip isn't showing until I remove the mouse from it and re-hover over the element again.
I want the tooltip to be shown instantly when said button is clicked. How can I achieve this? Is there a way to "refresh", in lack of better words, an html element?
try this way
Demo :
http://jsfiddle.net/dreamweiver/9z404crn/
$(document).ready(function() {
$('#example').tooltip();
$('#example').on('click', function() {
$(this).attr('data-original-title', 'changed tooltip');
$('#example').tooltip();
$(this).mouseover();
});
});
h3 {
margin-top: 50px;
}
<h3>
Sensors Permissions
<i class="icon-info-sign" data-toggle="tooltip" title="first tooltip" id='example'></i>
</h3>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet" />
<script src="https://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
Note:
Above logic works only with Bootstrap version 2.3.2 and below, however, the solution provided by #NabiK.A.Z's would work with the latest versions of Bootstrap lib.
Happy Coding:)
You can use this code:
var newTooltip = 'Changed this tooltip!';
$('#example').attr('data-original-title', newTooltip).parent().find('.tooltip-inner').html(newTooltip);
I test it with bootstrap 3.3.4
You can see it here:
http://jsfiddle.net/NabiKAZ/a4WwQ/1029/
$('a[data-toggle="tooltip"]').tooltip({
animated: 'fade',
placement: 'bottom',
});
$('.mytooltip').hover(function() {
$('.mytooltip').tooltip('show');
});
$('.mytooltip').click(function() {
var newTooltip = 'Changed this tooltip!';
$(this).attr('data-original-title', newTooltip).parent().find('.tooltip-inner').html(newTooltip);
});
.cart {
overflow: hidden;
padding: 10px 3px;
background: yellow;
}
<div class="cart">
<a data-toggle="tooltip" title="add to cart" class="mytooltip">
<i class="icon-shopping-cart"></i>
</a>
</div>
<br>
<div>
<a data-toggle="tooltip" title="add to another cart" class="mytooltip">
<i class="icon-shopping-cart"></i>
</a>
</div>
<!-- Post Info -->
<div style='position:fixed;bottom:0;left:0;
background:lightgray;width:100%;'>
About this SO Question: <a href='http://stackoverflow.com/q/19630749/1366033'>How to make bootstrap 3 tooltip work with parent div with overflow:hidden?</a><br/> Find documentation: <a href='http://getbootstrap.com/javascript/#tooltips'>Bootstrap 3.0 ToolTips</a><br/> Fork This Skeleton Here <a href='http://jsfiddle.net/KyleMit/kcpma/'>Bootrsap 3.0 Skeleton</a><br/>
<div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<link href="https://netdna.bootstrapcdn.com/font-awesome/3.2.1/css/font-awesome.min.css" rel="stylesheet" />
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/js/bootstrap.min.js"></script>
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.4/css/bootstrap.min.css" rel="stylesheet" />
For me in bootstrap 4 this worked:
$("#xxx").tooltip("dispose").attr("title", "New Tooltip").tooltip()
It's 2021 and with Bootstrap 5(BS5) all answers on this here didn't help me. Most answers above updated the content of the $(element).parent().find('.tooltip-inner').html("This is a test"); generated by the tooltip plugin. However with BS5 the generated template for the tooltip has a unique ID which can be used to update the tooltip.
This example demonstrates a simple scenario: when the .copy_queue_id div is clicked, queue ID from its attribute is copied and hence the the tooltip is updated to notify the user
HTML Markup:
<div class="cursor-pointer text-primary copy_queue_id" data-queueid="123456" data-bs-toggle="tooltip" data-bs-placement="bottom" title="Click to copy"> 123456</small>
JS - JQuery
$(document).on('click', '.copy_queue_id', function(){
let node = $(this);
let id = node.data('queueid');
navigator.clipboard.writeText(id);
let tooltipid = node.attr('aria-describedby');
$("#"+tooltipid).find('.tooltip-inner').html('ID Copied!!');
})
Tested & works in BS5
Hope this helps others :)
Sure you just have to change the tooltips text within the onclick event
$('.tooltip-inner').html("This is a test");
I've created a jsfiddle for you as a demonstration http://jsfiddle.net/a4WwQ/59/
Currently it will change all visible tooltips text which isnt really a problem since you arent going to show more than one at at a time. That being said, you should consider modifying the code to point to the closest tooltip.
hope it helps!
in case you are looking to refresh the contents;
$('#example').tooltipster('content', 'i am superman!');
2021, Bootstrap 5: update this property data-bs-original-title.
You can also use Razor / Blazor with this, like this:
var title = propExamples.FirstOrDefault(q => q.Key == selectedType.Id).Value;
<div class="col-sm-2">
<img class="zoom-on-hover cursor-pointer fit-image grayout"
src="/lib/bootstrap-icons-1.5.0/info-lg.svg"
data-bs-toggle="tooltip" data-placement="bottom"
data-bs-original-title="#title" />
</div>
I am using Twitter Bootstrap to create collapsible sections of text. The sections are expanded when a + button is pressed. My html code as follows:
<div class="row-fluid summary">
<div class="span11">
<h2>MyHeading</h2>
</div>
<div class="span1">
<button type="button" class="btn btn-success" data-toggle="collapse" data-target="#intro">+</button>
</div>
</div>
<div class="row-fluid summary">
<div id="intro" class="collapse">
Here comes the text...
</div>
</div>
Is there a way to change the button to display - instead of + after the section is expanded (and change back to + when it is collapsed again)?
Additional information: I hoped there would be a simple twitter-bootstrap/css/html-based solution to my problem. All responses so far make use of JavaScript or PHP. Because of this I want to add some more information about my development environment: I want to use this solution inside a SilverStripe-based (version 3.0.5) website which has some implications for the use of both PHP as well as JavaScript.
try this. http://jsfiddle.net/fVpkm/
Html:-
<div class="row-fluid summary">
<div class="span11">
<h2>MyHeading</h2>
</div>
<div class="span1">
<button class="btn btn-success" data-toggle="collapse" data-target="#intro">+</button>
</div>
</div>
<div class="row-fluid summary">
<div id="intro" class="collapse">
Here comes the text...
</div>
</div>
JS:-
$('button').click(function(){ //you can give id or class name here for $('button')
$(this).text(function(i,old){
return old=='+' ? '-' : '+';
});
});
Update With pure Css, pseudo elements
http://jsfiddle.net/r4Bdz/
Supported Browsers
button.btn.collapsed:before
{
content:'+' ;
display:block;
width:15px;
}
button.btn:before
{
content:'-' ;
display:block;
width:15px;
}
Update 2 With pure Javascript
http://jsfiddle.net/WteTy/
function handleClick()
{
this.value = (this.value == '+' ? '-' : '+');
}
document.getElementById('collapsible').onclick=handleClick;
Here's another CSS only solution that works with any HTML layout.
It works with any element you need to switch. Whatever your toggle layout is you just put it inside a couple of elements with the if-collapsed and if-not-collapsed classes inside the toggle element.
The only catch is that you have to make sure you put the desired initial state of the toggle. If it's initially closed, then put a collapsed class on the toggle.
It also requires the :not selector, so it doesn't work on IE8.
HTML example:
<a class="btn btn-primary collapsed" data-toggle="collapse" href="#collapseExample">
<!--You can put any valid html inside these!-->
<span class="if-collapsed">Open</span>
<span class="if-not-collapsed">Close</span>
</a>
<div class="collapse" id="collapseExample">
<div class="well">
...
</div>
</div>
Less version:
[data-toggle="collapse"] {
&.collapsed .if-not-collapsed {
display: none;
}
&:not(.collapsed) .if-collapsed {
display: none;
}
}
CSS version:
[data-toggle="collapse"].collapsed .if-not-collapsed {
display: none;
}
[data-toggle="collapse"]:not(.collapsed) .if-collapsed {
display: none;
}
JS Fiddle
Add some jquery code, you need jquery to do this :
<script>
$(".btn[data-toggle='collapse']").click(function() {
if ($(this).text() == '+') {
$(this).text('-');
} else {
$(this).text('+');
}
});
</script>
All the other solutions posted here cause the toggle to get out of sync if it is double clicked. The following solution uses the events provided by the Bootstrap framework, and the toggle always matches the state of the collapsible element:
HTML:
<div class="row-fluid summary">
<div class="span11">
<h2>MyHeading</h2>
</div>
<div class="span1">
<button id="intro-switch" class="btn btn-success" data-toggle="collapse" data-target="#intro">+</button>
</div>
</div>
<div class="row-fluid summary">
<div id="intro" class="collapse">
Here comes the text...
</div>
</div>
JS:
$('#intro').on('show', function() {
$('#intro-switch').html('-')
})
$('#intro').on('hide', function() {
$('#intro-switch').html('+')
})
That should work for most cases.
However, I also ran into an additional problem when trying to nest one collapsible element and its toggle switch inside another collapsible element. With the above code, when I click the nested toggle to hide the nested collapsible element, the toggle for the parent element also changes. It may be a bug in Bootstrap. I found a solution that seems to work: I added a "collapsed" class to the toggle switches (Bootstrap adds this when the collapsible element is hidden but they don't start out with it), then added that to the jQuery selector for the hide function:
http://jsfiddle.net/fVpkm/87/
HTML:
<div class="row-fluid summary">
<div class="span11">
<h2>MyHeading</h2>
</div>
<div class="span1">
<button id="intro-switch" class="btn btn-success collapsed" data-toggle="collapse" data-target="#intro">+</button>
</div>
</div>
<div class="row-fluid summary">
<div id="intro" class="collapse">
Here comes the text...<br>
<a id="details-switch" class="collapsed" data-toggle="collapse" href="#details">Show details</a>
<div id="details" class="collapse">
More details...
</div>
</div>
</div>
JS:
$('#intro').on('show', function() {
$('#intro-switch').html('-')
})
$('#intro').on('hide', function() {
$('#intro-switch.collapsed').html('+')
})
$('#details').on('show', function() {
$('#details-switch').html('Hide details')
})
$('#details').on('hide', function() {
$('#details-switch.collapsed').html('Show details')
})
I liked the CSS-only solution from PSL, but in my case I needed to include some HTML in the button, and the content CSS property is showing the raw HTML with tags in this case.
In case that could help someone else, I've forked his fiddle to cover my use case: http://jsfiddle.net/brunoalla/99j11h40/2/
HTML:
<div class="row-fluid summary">
<div class="span11">
<h2>MyHeading</h2>
</div>
<div class="span1">
<button class="btn btn-success collapsed" data-toggle="collapse" data-target="#intro">
<span class="show-ctrl">
<i class="fa fa-chevron-down"></i> Expand
</span>
<span class="hide-ctrl">
<i class="fa fa-chevron-up"></i> Collapse
</span>
</button>
</div>
</div>
<div class="row-fluid summary">
<div id="intro" class="collapse">
Here comes the text...
</div>
</div>
CSS:
button.btn .show-ctrl{
display: none;
}
button.btn .hide-ctrl{
display: block;
}
button.btn.collapsed .show-ctrl{
display: block;
}
button.btn.collapsed .hide-ctrl{
display: none;
}
My following JS solution is better than the other approaches here because it ensures that it will always say 'open' when the target is closed, and vice versa.
HTML:
<a href="#collapseExample" class="btn btn-primary" data-toggle="collapse" data-toggle-secondary="Close">
Open
</a>
<div class="collapse" id="collapseExample">
<div class="well">
...
</div>
</div>
JS:
$('[data-toggle-secondary]').each(function() {
var $toggle = $(this);
var originalText = $toggle.text();
var secondaryText = $toggle.data('toggle-secondary');
var $target = $($toggle.attr('href'));
$target.on('show.bs.collapse hide.bs.collapse', function() {
if ($toggle.text() == originalText) {
$toggle.text(secondaryText);
} else {
$toggle.text(originalText);
}
});
});
Examples:
$('[data-toggle-secondary]').each(function() {
var $toggle = $(this);
var originalText = $toggle.text();
var secondaryText = $toggle.data('toggle-secondary');
var $target = $($toggle.attr('href'));
$target.on('show.bs.collapse hide.bs.collapse', function() {
if ($toggle.text() == originalText) {
$toggle.text(secondaryText);
} else {
$toggle.text(originalText);
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<link href="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/css/bootstrap-combined.min.css" rel="stylesheet"/>
<script src="http://netdna.bootstrapcdn.com/twitter-bootstrap/2.3.1/js/bootstrap.min.js"></script>
<a href="#collapseExample" class="btn btn-primary" data-toggle="collapse" data-toggle-secondary="Close">
Open
</a>
<div class="collapse" id="collapseExample">
<div class="well">
...
</div>
</div>
JS Fiddle
Other benefits of this approach:
the code is DRY and reusable
each collapse button stays separate
you only need to put one change into the HTML: adding the data-toggle-secondary attribute
I guess you could look inside your downloaded code where exactly there is a + sign (but this might not be very easy).
What I'd do?
I'd find the class/id of the DOM elements that contain the + sign (suppose it's ".collapsible", and with Javascript (actually jQuery):
<script>
$(document).ready(function() {
var content=$(".collapsible").html().replace("+", "-");
$(".collapsible").html(content));
});
</script>
edit
Alright... Sorry I haven't looked at the bootstrap code... but I guess it works with something like slideToggle, or slideDown and slideUp... Imagine it's a slideToggle for the elements of class .collapsible, which reveal contents of some .info elements. Then:
$(".collapsible").click(function() {
var content=$(".collapsible").html();
if $(this).next().css("display") === "none") {
$(".collapsible").html(content.replace("+", "-"));
}
else $(".collapsible").html(content.replace("-", "+"));
});
This seems like the opposite thing to do, but since the actual animation runs in parallel, you will check css before animation, and that's why you need to check if it's visible (which will mean it will be hidden once the animation is complete) and then set the corresponding + or -.
Easier with inline coding
<button type="button" ng-click="showmore = (showmore !=null && showmore) ? false : true;" class="btn float-right" data-toggle="collapse" data-target="#moreoptions">
<span class="glyphicon" ng-class="showmore ? 'glyphicon-collapse-up': 'glyphicon-collapse-down'"></span>
{{ showmore !=null && showmore ? "Hide More Options" : "Show More Options" }}
</button>
<div id="moreoptions" class="collapse">Your Panel</div>
Some may take issue with changing the Bootstrap js (and perhaps validly so) but here is a two line approach to achieving this.
In bootstrap.js, look for the Collapse.prototype.show function and modify the this.$trigger call to add the html change as follows:
this.$trigger
.removeClass('collapsed')
.attr('aria-expanded', true)
.html('Collapse')
Likewise in the Collapse.prototype.hide function change it to
this.$trigger
.addClass('collapsed')
.attr('aria-expanded', false)
.html('Expand')
This will toggle the text between "Collapse" when everything is expanded and "Expand" when everything is collapsed.
Two lines. Done.
EDIT: longterm this won't work. bootstrap.js is part of a Nuget package so I don't think it was propogating my change to the server. As mentioned previously, not best practice anyway to edit bootstrap.js, so I implemented PSL's solution which worked great. Nonetheless, my solution will work locally if you need something quick just to try it out.
You do like this.
the function return the old text.
$('button').click(function(){
$(this).text(function(i,old){
return old=='Read More' ? 'Read Less' : 'Read More';
});
});
Applied and working in Bootstrap 5.0.1.
Using simple jQuery
jQuery('button').on( 'click', function(){
if(jQuery(this).hasClass('collapsed')){
jQuery(this).html('+');
} else {
jQuery(this).html('-');
}
});
You can also use font awesome or HTML instead of +/- signs.