Checkbox input triggering Bootstrap accordion collapse event - javascript

Hello guys I'm using Bootstrap 5 accordion, the only problem I have is that the input checkbox is triggering the "collapse" event from the accordion, I tried to move the checkbox outside the range of the button from the accordion but that will look horrible.
I'm using Svelte, rendering each accordion with Each block with Data from the backend!
This is my code right now:
<div class="container">
<div class="row">
<div class="col-md-10 col-10 col-sm-10 responsiveFix">
<div class="accordion" id="accordionObjective">
{#each objectives as objective}
<div class="accordion-item">
<h2
class="accordion-header"
id={"heading" + objective.objectiveId}
>
<button
class="accordion-button objectiveTitle collapsed"
type="button"
data-bs-toggle="collapse"
data-bs-target={"#collapse" +
objective.objectiveId}
aria-expanded="false"
aria-controls={"collapse" +
objective.objectiveId}
>
<div class="form-check">
<input
class="form-check-input"
type="checkbox"
value={objective.objectiveId}
id="myCollapse"
checked={objective.value}
on:click={postObjective(
objective.objectiveId,
objective.value
)}
/>
</div>
<span> {objective.title}</span>
</button>
</h2>
<div
id={"collapse" + objective.objectiveId}
class="accordion-collapse collapse"
aria-labelledby={"heading" +
objective.objectiveId}
data-bs-parent="#accordionObjective"
>
<div class="accordion-body">
<span>{objective.description}</span>
</div>
</div>
</div>
{/each}
</div>
</div>
</div>
</div>
The output of this code its
and this is the picture showing my problem after clicking on any checkbox:
I also tried to bind a bootstrap 5 function to the checkbox input but it didn't work
What can I do? Can you throw me any clue? Thank you!

I am not familiar with Bootstrap 5 as such, but a quick glance at your code shows this: <button on:click={postObjective(objective.objectiveId, objective.value )}>
This function is executed at render time and the return value added as the event listener for your on:click
The correct syntax would be <button on:click={() => postObjective(....)}>
As the code is now it probably does not do what you expect.
Edit:
In your case the input is also inside a button, clicking the input will therefore also click the button. To stop this from happening you have to prevent the event from bubbling up, Svelte has a handy helper for that: <button on:click|stopPropagation={() => postObjective(....)}>

Related

How can i continuesly using appenTo() when i click a button?

im trying to reverse div with Jquery which when i click a button the divs will reverse and switch place
<div class="player1">
<div class="player1-a">
<div class="pemain p1a">
<h4>Samsudin</h4>
</div>
<div class="cock 1a">
</div>
</div>
<div class="player1-b">
<div class="pemain p1b">
<h4>Joko</h4>
</div>
<div class="cock 1b">
</div>
</div>
</div>
<button class="btn btn-light score_plus" id="score_kiri"><h1>SCORE</h1></button>
whenever this button clicked the div p1b will move to div player1-a and so do div p1a will move to div player1-b.
Here's my jquery code that the divs only move once and dont move again when i click again.
$('#score_kiri').click(function() {
$('#player_kiri').val(i++);
$('.p1a').appendTo('.player1-b');
$('.1a').appendTo('.player1-b');
$('.p1b').appendTo('.player1-a');
$('.1b').appendTo('.player1-a');
$('.p1a').append('.player1-b');
$('.1a').append('.player1-b');
$('.p1b').append('.player1-a');
$('.1b').append('.player1-a');
});
Your issue is that you have hard-coded the elements to move, rather than use relative positions. Effectively saying "make it exactly like this" rather than "move the first one to the end" (which I believe is what you're trying to do).
You can select the first one various ways, here's one:
$(".player1 > div").first()
Using .appendTo(".player1") with this will move the element to the end - so by always moving the first to the end you get your "continuously appendTo". If you have 3, then first will move to the end each time.
This is slightly different from "switching places" but has the same effect when only 2.
Updated snippet:
$("#btn").click(() =>
$(".player1 > div").first().appendTo(".player1")
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="player1">
<div class="player1-a">
<div class="pemain p1a">
<h4>p1a Samsudin</h4>
</div>
<div class="cock 1a">1a
</div>
</div>
<div class="player1-b">
<div class="pemain p1b">
<h4>p1b Joko</h4>
</div>
<div class="cock 1b">
1b
</div>
</div>
</div>
<button id=btn>
click me
</button>

How to disable link on Button but when I click on card link should be work

I am Using card and when i click on card its work fine. Now i have added three buttons in cards when i click on button then card link also call. i just want to perform different action from button but not card link.
This is code:
<li class="t-Cards-item #CARD_MODIFIERS#" data-id="#ID#" >
<div class="click t-Card" >
<a href="javascript:void(null);" class="t-Card-wrap" data-id="#ID#">
<div class="t-Card-icon u-color #CARD_COLOR#"><span class="t-Icon fa #CARD_ICON#"><span class="t-Card-initials" role="presentation">#CARD_INITIALS#</span></span></div>
<div class="t-Card-titleWrap"><h3 class="t-Card-title">#CARD_TITLE#</h3>
<h4 class="t-Card-subtitle">#CARD_SUBTITLE#</h4></div>
<div id="outer">
<div class="inner"><button class="msgBtn" >S</button></div>
<div class="inner"><button class="msgBtn2" onClick="return false;">M</button></div>
<div class="inner"><button class="msgBtnBack">L</button></div>
</div>
<div class="t-Card-body">
<div class="t-Card-desc">#CARD_TEXT#</div>
<div class="t-Card-info">#CARD_SUBTEXT#</div>
</div>
<span class="t-Card-colorFill u-color #CARD_COLOR#"></span>
</a>
</div>
</li>
The Problem
Assume there are two divs with two different buttons on them.
<div onClick={handleOutter}>
<div onClick={handleInner}>
// some content ...
</div>
</div>
calling handleOutter will call the handleInner function. this is the default behavior of event propagation in your elements. more info on MDN documentation.
The Solution
You can stop event propagation in the child elements by adding event.stopPropagation() in the handler function in this way:
const btn = document.getElementById('myParentElement');
btn.onclick = function (event){
event.stopPropagation();
// ...
}
more info on MDN documentation.

expand menu to expand/collapse all menues regardless if they are expanded or closed

I have 4 expandable menus and 5 buttons. Collapse first button expands/closes the first menu, Collapse second button expands/closes the second menu and so on.
As it is: Button Collapse all for each menu closes it if it is expanded and expands it if it is closed.
Want to be: Whereas I want my Collapse all button to expand all menus if they are closed and don't change them if they are expanded. And then if clicked again closes all the menus that are expanded and don't change the closed menus.
Here is a fiddle I wrote for As it is: expand menu fidlle
.row {
background: #f8f9fa;
margin-top: 20px;
}
.col {
border: solid 1px #6c757d;
padding: 10px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/js/bootstrap.js"></script>
<link href="https://stackpath.bootstrapcdn.com/bootstrap/4.4.1/css/bootstrap.css" rel="stylesheet"/>
<p>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample1, #collapseExample2, #collapseExample3, #collapseExample4" aria-expanded="false" aria-controls="collapseExample">
Collapse all
</button>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample1" aria-expanded="false" aria-controls="collapseExample">
Collapse first
</button>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample2" aria-expanded="false" aria-controls="collapseExample">
Collapse second
</button>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample3" aria-expanded="false" aria-controls="collapseExample">
Collapse third
</button>
<button class="btn btn-primary" type="button" data-toggle="collapse" data-target="#collapseExample4" aria-expanded="false" aria-controls="collapseExample">
Collapse fourth
</button>
</p>
<div class="collapse" id="collapseExample1">
<div class="card card-body">
hi first
</div>
</div>
<div class="collapse" id="collapseExample2">
<div class="card card-body">
hi second
</div>
</div>
<div class="collapse" id="collapseExample3">
<div class="card card-body">
hi third
</div>
</div>
<div class="collapse" id="collapseExample4">
<div class="card card-body">
hi fourth
</div>
</div>
How can I do it?
A naive solution I can think of now is to bind the collapse all click event via a custom handler that shows or hides all collapsibles based on a state on the collapse all button, instead of via Bootstrap built-in data-toggle="collapse" and data-target="*".
<p>
<button id="toggle-all" class="btn btn-primary" type="button">
Collapse all
</button>
<button class="btn btn-primary" type="button" data-toggle="collapse" ... />
...
</p>
<div class="collapse" />
...
Then in this Collapse all's button click event, you can have a state on this button itself (via data-) to memorize whether to show or hide all collapsibles. And based on that state variable, you can call either .collapse('show') or .collapse('hide') on all collapsibles manually.
The show method won't show a collapsible again if it's already shown. And the hide method won't hide a collapsible if it's already hidden.
$(function() {
$('#toggle-all').click(function() {
// Declare a variable, `data-to-show`, to contain the state whether to show/hide
// all collapsibles.
// It defaults to true, which means it's about to show all.
if (!$(this).data('to-show')) {
$(this).data('to-show', true);
} else {
$(this).data('to-show', !$(this).data('to-show'));
}
if ($(this).data('to-show')) {
$('.collapse').collapse('show');
} else {
$('.collapse').collapse('hide');
}
return false;
});
});
demo: https://jsfiddle.net/davidliang2008/cvy2kbpz/28/
Another better "solution" I can think of is to declare an extra data attribute, maybe something like data-toggle-all-at-the-same-time="true", and override Bootstrap's built-in .collapse() so that when it sees that data attribute being true, it doesn't toggle the target elements which are already toggled?
Sadly I haven't found an easy way to do so, yet.
I would use the toggle function from jQuery. Here is a link to its docs https://api.jquery.com/toggle/
This function hides an element if it is beign shown; or shows it if it is hidden. Simple and works like a charm without many checks.
You need to include jQuery onto your html page. Right at the bottom.
Let this script be the last element within your body tag.
Then you will need to include all the javascript files that come within the boostrap folder (if you have downloaded the folder).
Add the following tags on your script. As mentioned, right before the tag
<script src="https://code.jquery.com/jquery-3.5.1.slim.min.js" integrity="sha384-DfXdz2htPH0lsSSs5nCTpuj/zy4C+OGpamoFVy38MVBnE+IbbVYUew+OrCXaRkfj" crossorigin="anonymous"></script>
<script src="https://cdn.jsdelivr.net/npm/popper.js#1.16.1/dist/umd/popper.min.js" integrity="sha384-9/reFTGAW83EW2RDu2S0VKaIzap3H66lZH81PoYlFhbGU+6BZp6G7niu735Sk7lN" crossorigin="anonymous"></script>
<script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.2/js/bootstrap.min.js" integrity="sha384-B4gt1jrGC7Jh4AgTPSdUtOBvfO8shuf57BaghqFfPlYxofvL8/KUEfYiJOMMV+rV" crossorigin="anonymous"></script>

ngx-bootstrap when modal height is dynamic scroll is not coming

I want to change the height of modal dynamically whenever the content inside the modal is expanding or collapsing. The scenario is I have a collapsible aria inside the modal which expands when view answer button gets clicked. Now while first time loading if content height of modal needs scroll then even after view answer button click everything works fine. But if initial height does not need a scroll that time even after expanding the content scroll is not coming which blocks user to perform further actions.
Screens:
Before expanding screen before clicking view answer button
After expanding screen after clicking view answer button. Here I need scroll otherwise user will get blocked
Code:
<ng-template #template>
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLongTitle">New question</h5>
</div>
<div class="modal-body">
<p class="text-left padding-b-10 border-b-q" [innerHTML]="'Q. ' + questions[nextQuestionIndex].question"></p>
<p class="text-left padding-b-10 border-b-q" (click)="handleOptionClick(i)" *ngFor="let option of questions[nextQuestionIndex].options; let i = index">
{{i + '. '}}<span [innerHTML]="option" [ngClass]="{'text-success': (questions[nextQuestionIndex].answer === i) && optionValidationArr[i],'text-danger': (questions[nextQuestionIndex].answer !== i) && optionValidationArr[i]}"></span><span class="float-right"
[ngClass]="{'text-success': (questions[nextQuestionIndex].answer === i) && optionValidationArr[i]}" *ngIf="(questions[nextQuestionIndex].answer === i) && optionValidationArr[i]">You are right</span><span class="float-right" [ngClass]="{'text-danger': (questions[nextQuestionIndex].answer !== i) && optionValidationArr[i]}"
*ngIf="(questions[nextQuestionIndex].answer !== i) && optionValidationArr[i]">Please try again</span>
</p>
<div class="container">
<p>
<a class="btn btn-outline-danger" data-toggle="collapse" href="#multiCollapseExample1" role="button" aria-expanded="false" aria-controls="multiCollapseExample1">View answer</a>
</p>
<p class="text-danger">This will reduce your score please try your best before viewing the answer</p>
<div class="collapse multi-collapse" id="multiCollapseExample1">
<div class="card card-body">
Correct answer: <span class="text-success">{{questions[nextQuestionIndex].answer}}</span><br> Explaination: <span></span>
</div>
</div>
</div>
<hr />
<div class="progress">
<div class="progress-bar bg-success progress-bar-animated progress-bar-striped" role="progressbar" [style.width.%]="progress.correctPer" [attr.aria-valuenow]="progress.correctPer" aria-valuemin="0" aria-valuemax="100">{{(progress.correctPer ? (progress.correctPer + '%'):'')}}</div>
<div class="progress-bar bg-danger progress-bar-animated progress-bar-striped" role="progressbar" [style.width.%]="progress.wrongPer" [attr.aria-valuenow]="progress.wrongPer" aria-valuemin="0" aria-valuemax="100">{{(progress.wrongPer ? (progress.wrongPer+'%'):'')}}</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn btn-outline-danger" (click)="closeModal()">End practice</button>
<button type="button" class="btn btn-outline-primary" (click)="getNextQuestion(template, resultTemplate)">{{(((questionArrLen-1) !== nextQuestionIndex) ? "Next question" : "View result")}}</button>
</div>
</ng-template>
How about do it like this?
Add a class on modal-body and set height and overflow.
<div class="modal-body question-modal-body">
</div>
.question-modal-body {
max-height: 150px; // set the height which the answer is not shown
overflow: auto;
}
Looks so late to the party, just hope my answer helps someone later. After seeing your screenshot, I suggest having a "Modal scrollable content" approach for your UI. So, only the "content" will expand and push the modal height to the maximum of the screen height ( not over screen height ). So, the modal header and footer will always keep visible, and the content area is scrollable.
Please check the demo on the following Codepen I have made: https://codesandbox.io/s/ngx-boostrap-scrollable-modal-69jox.
It is using:
bootstrap#4.6.1 ( as seen in index.html )
ngx-bootstrap#7.1.2
The trick is to have a special class added to the modal when doing modalService.show(). You can see it at /src/app/app.component.ts
openModal(template: TemplateRef<any>) {
this.modalRef = this.modalService.show(template, {
class: "modal-dialog-centered modal-dialog-scrollable"
});
}
The class name I have mentioned earlier was modal-dialog-scrollable. About modal-dialog-centered is just my personal preference to have the dialog always get centered.
More about "Modal option" used above can be found at the documentation here: https://valor-software.com/ngx-bootstrap/old/5.6.0/#/modals#modal-options
Hope this answer helps someone. Thanks :)

Jquery not recognizing events that takes place on the HTML templates that is generated on fly

I am using Handlerbars.js and it gives me a dynamic template that is generated on the fly. When I do some Jquery events like click etc .. Jquery is not able to catch those events. Please help me out.
I want to trigger a event when the button with id hitUp is clicked
HandlerBar.js code
{{#each this}}
<div id="accordion2" class="panel-group">
<div class="panel panel-default">
<div class="panel-heading">
<h4 class="panel-title">
<a href="#{{log}}" data-parent="#accordion2"
data-toggle="collapse" class="btn-block" > <img
class="img-rounded" src="/assets/images/default-food.png" /> {{log}}
</a>
</h4>
</div>
<div class="panel-collapse collapse" id="{{log}}">
<div class="panel-body food-details">
<div class="bm pzero col-xs-12">
<div class="input-group spinner">
<input id="spinid" type="text"
name="demo_vertical2" class="form-control input-sm"
/> <span class="input-group-btn vertical">
<button id="hitUp"
class="btn btn-default bootstrap-touchspin-up"
type="button">
<i class="fa fa-caret-up"></i>
</button>
<button id="hitDown"
class="btn btn-default bootstrap-touchspin-down "
type="button">
<i class="fa fa-caret-down"></i>
</button>
</span>
</div>
HTML code
<div id="accordion2" class="panel-group">
</div>
Jquery code
Try1
$('body').on("click",'#hitUp',function(){
console.log("Functionclicked")
});
Try2
$('#hitUp').click(function(){
console.log("Functionclicked")
});
Try3
$( document ).ready(function( $('body').on("click",'#hitUp',function(){
console.log("Functionclicked")
});){})
I have tried the above Jquery methods but no use. Give me some solutions
Just like in the link that #adeno posted, jQuery event handlers need to be registered as the very last thing that happens when all the JavaScript files and libraries are loaded. Calling $(document).ready() does not mean that all JS files have been loaded, it just means that the DOM has been put in place and is ready for manipulation. If you're going to do more DOM manipulation with a library like Handlebars, you need to make sure that your event handlers are registered after all that dynamic generation has already happened.
So if this is my template:
<h1>{{title}}</h1>
<div>{{body}}</h1>
<br />
{{#each buttonIds}}
<input type="button" id="{{this}}" value="Click me" />
{{/each}}
And this is my javascript:
var data = {
title: 'The Title',
body: 'Document Body',
buttonIds: [ 'hitUp1', 'hitUp2', 'hitUp3' ]
};
var templateScript = $('#header').html();
var template = Handlebars.compile(templateScript);
$(document.body).append(template(data));
$('#hitUp1').on('click', function () { alert('clicked 1'); });
$('#hitUp2').on('click', function () { alert('clicked 2'); });
$('#hitUp3').on('click', function () { alert('clicked 3'); });
I'm waiting til very last to register the on click handlers, and they are each unique identifiers.
Here is a working fiddle to demonstrate what I'm saying.
was facing the same issue. use
$('body').on("change", '#amountType', function (){
});
this worked for me

Categories