How to activate bootstrap modal after selecting files in input in Vue 3? - vuejs3

So, I'm doing a chat component and we've the option to send files, but prior to send it the user must review it and for it i had the idea to show a modal containing all the files selected, but i just can't show the modal right after the file selection, i tried getElementById but it did not work.
Here's my template:
<input type="file" multiple name="file" id="fileInput" class="hidden-input" #change="onChange"
ref="file" accept=".pdf,.jpg,.jpeg,.png" hidden />
<button type="button" #click="chooseFiles()" class="btn btn-link text-decoration-none emoji-btn"
id="emoji-btn">
<i class="las la-arrow-up align-middle" />
</button>
And here's my script:
chooseFiles() {
document.getElementById("fileInput").click()
// document.getElementById("showModal").click()
},
onChange(e) {
this.$refs.file.files = e.target.files
this.files.push(...this.$refs.file.files)
this.fileSize(e)
// document.getElementById("showModal").click()
},
And here is the modal:
<div id="showModal" class="modal fade" ref="modal" tabindex="-1" aria-labelledby="myModalLabel">
<div class="modal-dialog modal-lg">
<div class="modal-content">
<div class="modal-body">
<div v-for="file in files" :key="file.name" class="preview-card border rounded">
<div class="d-flex align-items-center p-2">
<b-img v-if="file.type != 'application/pdf'" class="img-thumbnail me-2" alt="200x200" width="200"
:src="generateURL(file)" data-holder-rendered="true" />
<iframe v-else class="img-thumbnail me-2" data-holder-rendered="true" frameBorder="0" scrolling="no"
alt="200x200" width="200" :src="generateURL(file)" />
<div class="flex-grow-1">
<div class="pt-1">
<h5 class="fs-11 mb-1" data-dz-name="">
{{ file.name }}
</h5>
<p class="fs-9 text-muted mb-0" data-dz-size="">
<strong>{{ (file.size / 1024) / 1000 }}</strong> MB
</p>
<strong class="error text-danger" data-dz-errormessage="" />
</div>
</div>
</div>
</div>
</div>
<div class="modal-footer">
<b-button type="button" class="btn btn-danger" data-bs-dismiss="modal">
Sair
</b-button>
</div>
</div>
</div>
</div>

When I was commenting I missed the fact this was tagged bootstrap-modal, so I understand now you're wanting to open a bootstrap modal which has a specific method for activation. For bootstrap 5 you can get the Modal instance with bootstrap.Modal.getOrCreateInstance(). Assign this to a data property and then you can call all the typical modal methods on it like .show(), .toggle(), .hide(), etc. Below is a working example using a more simplified modal than your own just for simplicity sake.
<div id="app">
<input type="file" multiple name="file" id="fileInput" class="hidden-input" #change="onChange"
ref="file" accept=".pdf,.jpg,.jpeg,.png" hidden />
<button type="button" #click="chooseFiles" class="btn btn-link text-decoration-none emoji-btn"
id="emoji-btn">
choose files
</button>
<!-- Modal -->
<div class="modal fade" ref="modal" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Files</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
<div v-for="(file, i) in files" :key="i">
{{ file.name }}
</div>
</div>
</div>
</div>
</div>
</div>
data() {
return {
files: [],
modal: null
}
},
mounted() {
const myModalEl = this.$refs.modal
this.modal = bootstrap.Modal.getOrCreateInstance(myModalEl)
},
methods: {
chooseFiles() {
this.$refs.file.click()
},
onChange(e) {
this.$refs.file.files = e.target.files
this.files.push(...this.$refs.file.files)
this.modal.show()
},
}
and here is the sandbox with the above code
If bootstrap 5 is installed as a package you can do this instead:
import { Modal } from "bootstrap";
.
.
.
mounted() {
this.modal = new Modal(this.$refs.modal);
}

Related

Can I call data-bs-target after response data is true?

'My vue code like this :'
<teleport to="body">
<div v-show="success" id="msgModal" class="modal fade" tabindex="-1">
<div class="modal-dialog modal-dialog-centered modal-dialog-scrollable">
<div class="modal-content">
<div class="modal-header bg-light">
<h5 class="modal-title">applyed successed!</h5>
<button type="button" data-bs-dismiss="modal" aria-label="Close">
<font-awesome-icon icon="times" />
</button>
</div
</div>
</div>
</div>
</teleport>
<script>
function callBackEndFunc(){
if(condition){
api.apiMethod1({})
.then(() => {
alert("success!");
//want to call data-bs-target="#msgModal"
});
}
}
</script>
When callBackEndFunc was called and after ajax success
want to want to call data-bs-target="#msgModal" to show div message in #msgModal.
Can anyone give me some advisor how to solve this problem?

OnGetAsync catches v1 of my button but do not catch v2 with pop-up

I have little problem. I am going to implement Bootstrap modal with loading some data from database on click, but i am stuck at this:
-> this works just fine and catches click:
<div class="card-body">
<p class="card-text">
<b>Id:</b> #post.Id <br />
<b>Title:</b> #post.Title<br />
<b>Description:</b> #post.Description<br />
<b>Nick:</b> #post.Author<br />
<b>Category:</b> #post.Category<br />
<b>Creation Time:</b> #post.CreationTime</p>
<hr />
<form method="post">
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Your comment" name="comment">
<span class="input-group-text"></span>
<input type="text" class="form-control" placeholder="Your nick" name="author">
<button class="btn btn-success" asp-route-postid="#post.Id" asp-route-comment="comment" asp-route-author="author"> Add comment </button>
</div>
</form>
<form method="get">
<div class="py-2">
<button type="submit" name="Id" value="#post.Id" class="btn btn-primary">Load</button>
</div>
</form>
#foreach(var comment in Model.Comments.Where(x=>x.PostId == #post.Id))
{
<b>Comment: </b>#comment.CommentDescription <b>Author: </b>#comment.CommentAuthor <b>Creation Time: </b>#comment.CreationTime<br />
}
</div>
but after implementing Modal it wont work anymore. My front-end looks like this:
<div class="card-header">
<center> <b>Post</b></center>
</div>
<div class="card-body">
<p class="card-text">
<b>Id:</b> #post.Id <br />
<b>Title:</b> #post.Title<br />
<b>Description:</b> #post.Description<br />
<b>Nick:</b> #post.Author<br />
<b>Category:</b> #post.Category<br />
<b>Creation Time:</b> #post.CreationTime</p>
<hr />
<form method="post">
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Your comment" name="comment">
<span class="input-group-text"></span>
<input type="text" class="form-control" placeholder="Your nick" name="author">
<button class="btn btn-success" asp-route-postid="#post.Id" asp-route-comment="comment" asp-route-author="author"> Add comment </button>
</div>
</form>
<!-- Modal -->
<form method="get">
<div class="py-2">
<button type="button" name="Id" value="#post.Id" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">Show comments</button>
<button type="submit" name="Id" value="#post.Id" class="btn btn-primary">Load</button>
</div>
</form>
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Comments</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
#foreach(var comment in Model.Comments.Where(x=>x.PostId == #post.Id))
{
<b>Comment: </b>#comment.CommentDescription <b>Author: </b>#comment.CommentAuthor <b>Creation Time: </b>#comment.CreationTime<br />
}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
This is my OnGetAsync:
public async Task OnGetAsync(string category, int id)
{
//do something
}
Have you ever had similar problem or know workflow to fix it?
//update
After some work i found this:
<div class="card-body">
<p class="card-text">
<b>Id:</b> #post.Id <br />
<b>Title:</b> #post.Title<br />
<b>Description:</b> #post.Description<br />
<b>Nick:</b> #post.Author<br />
<b>Category:</b> #post.Category<br />
<b>Creation Time:</b> #post.CreationTime</p>
<hr />
<form method="post">
<div class="input-group mb-3">
<input type="text" class="form-control" placeholder="Your comment" name="comment">
<span class="input-group-text"></span>
<input type="text" class="form-control" placeholder="Your nick" name="author">
<button class="btn btn-success" asp-route-postid="#post.Id" asp-route-comment="comment" asp-route-author="author"> Add comment </button>
</div>
</form>
<!-- Modal -->
<form method="get">
<div class="py-2">
<button type="button" name="Id" value="#post.Id" class="btn btn-primary" data-bs-toggle="modal" data-bs-target="#exampleModal">Show comments</button>
<button type="submit" name="Id" value="#post.Id" class="btn btn-primary">Load</button>
</div>
</form>
<div class="modal fade" id="exampleModal" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Comments</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
#foreach(var comment in Model.Comments.Where(x=>x.PostId == #post.Id))
{
<b>Comment: </b>#comment.CommentDescription <b>Author: </b>#comment.CommentAuthor <b>Creation Time: </b>#comment.CreationTime<br />
}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
When clicking Load my comments are loaded and "Show comments" button actually shows them, but for every button it show the same comment.
In best way this should work like this:
After clicking "Show comments" its loading comments for single post.
In best way this should work like this: After clicking "Show comments"
its loading comments for single post.
That is because data-bs-target value are all the same so that it will trigger the same modal. You need specify it by adding suffix. Change your code to data-bs-target="#exampleModal_#post.Id" and id="exampleModal_#post.Id".
Whole code below:
//more code.....
<!-- Modal -->
<form method="get">
<div class="py-2">
//change here......
<button type="button" data-bs-target="#exampleModal_#post.Id" name="Id" value="#post.Id" class="btn btn-primary" data-bs-toggle="modal">Show comments</button>
<button type="submit" name="Id" value="#post.Id" class="btn btn-primary">Load</button>
</div>
</form>
//change here.........
<div class="modal fade" id="exampleModal_#post.Id" tabindex="-1" aria-labelledby="exampleModalLabel" aria-hidden="true">
<div class="modal-dialog modal-xl">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="exampleModalLabel">Comments</h5>
<button type="button" class="btn-close" data-bs-dismiss="modal" aria-label="Close"></button>
</div>
<div class="modal-body">
#foreach(var comment in Model.Comments.Where(x=>x.PostId == #post.Id))
{
<b>Comment: </b>#comment.CommentDescription <b>Author: </b>#comment.CommentAuthor <b>Creation Time: </b>#comment.CreationTime<br />
}
</div>
<div class="modal-footer">
<button type="button" class="btn btn-secondary" data-bs-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
</div>

Modal always getting first Id

I have a basic feedback section, where people can reply to people's feedback. When I click the Reply button, it is supposed to open modal with text to fill and have the FeedbackParentId set to the feedback that has been clicked. However, it is always set to the first feedback.
This is the loop where I simply show all the feedback on the page.
#foreach (var comment in Model.Feedback.OrderByDescending(x => x.CreatedOn))
{
<partial name="_CommentSectionPartial" model="comment" />
}
This is the comment partial itself. Why would the modal get the first ID always?
#model FeedbackViewModel
<div class="comment-list" id="#Model.Id">
<div class="single-comment justify-content-between d-flex">
<div class="user justify-content-between d-flex">
<div class="thumb">
<img src="~/images/blog/c3.jpg" alt="">
</div>
<div class="desc">
<h5>
#Model.Name
</h5>
<p class="date">#Model.CreatedOn.Value.ToLongDateString()</p>
<p class="comment">
#Model.Comment
</p>
</div>
</div>
<div class="reply-btn">
<div class="modal fade" id="replyModal" tabindex="-1" role="dialog" aria-labelledby="replyModalLabel" aria-hidden="true">
<div class="modal-dialog" role="document">
<div class="modal-content">
<div class="modal-header">
<h5 class="modal-title" id="replyModalLabel">Submit Feedback for #Model.Name</h5>
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
<span aria-hidden="true">×</span>
</button>
</div>
<div class="modal-body">
<form id="send-reply-form" asp-action="AddReply" asp-controller="Business" asp-area="Business">
<input type="hidden" name="feedbackparentId" value="#Model.Id" />
<input type="hidden" name="businessid" value="#Model.Business.Id" />
#Html.AntiForgeryToken()
<div class="form-group form-inline">
<div class="form-group col-lg-6 col-md-6 name">
<input type="text" name="authorName" class="form-control col-form-label" id="name" placeholder="Enter Name" onfocus="this.placeholder = ''" onblur="this.placeholder = 'Enter Name'">
</div>
<div class="form-group col-lg-6 col-md-6 email">
<input type="email" name="email" class="form-control" id="email" placeholder="Enter email address" onfocus="this.placeholder = ''" onblur="this.placeholder = 'Enter email address'">
</div>
</div>
<div class="form-group">
<textarea class="form-control mb-10" rows="5" name="comment" placeholder="Message" onfocus="this.placeholder = ''" onblur="this.placeholder = 'Message'"
required=""></textarea>
</div>
<button type="button" class="btn btn-secondary" data-dismiss="modal">Close</button>
<button type="submit" class="btn btn-primary">Send Feedback</button>
</form>
</div>
</div>
</div>
</div>
<button id="reply-button" type="button" class="btn btn-primary float-right" data-toggle="modal" data-target="#replyModal">Reply</button>
</div>
</div>
</div>
I tried setting the value through JS like that, does not work.
$(document).ready(function () {
$("#send-reply-form").click(function () {
$("#feedbackparentId").val($(this).data('id'));
});
});
I've fixed it with that piece of code:
$(document).on("click", "#reply-button", function () {
var feedbackId = $(this).data('id');
$(".modal-body #feedbackparentId").val(feedbackId);
console.log(feedbackId);
});

Why doesn't bootstrap detect the toggle-modal on a selected option?

I have been using the modal with links and it works as expected:
<a data-toggle="modal" data-target="#edit-multiple-70304842829540" data-remote="true" data-type="html" data-method="post" title="Edit Multiple" href="/contacts/edit_multiple">
<span class="fa fa-pencil-square-o" aria-hidden="true"></span>
</a>
<div class="modal fade" id="edit-multiple-70304842829540" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog modal-sizer">
<div class="modal-content">
<div class="modal-header" style="overflow: auto;">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h2 class="modal-title" id="myModalLabel">Edit Multiple</h2>
</div>
<div class="loading" style="display: none;">
<img src="/assets/spinner.gif" alt="Spinner">
</div>
<div class="modal-target">
...
</div>
</div>
</div>
</div>
I click on link and modal displays. However, I try this with an option element of a select form and the modal does not display:
<select name="global_filter_id" id="global_filter_id" data-remote="true" data-url="/contacts" data-params="card_position=card&contactable=Lead" data-type="html" class="form-control">
<option data-toggle="modal" data-target="filterEdit" data-url="/contacts/edit_multiple" data-remote="true" data-type="html" data-method="post" data-params="filterable_type=Lead" value="1">Edit/Delete Filter</option>
</select>
<div class="modal fade" id="filterEdit" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog modal-sizer">
<div class="modal-content">
<div class="modal-header" style="overflow: auto;">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h2 class="modal-title" id="myModalLabel">Edit/Delete Filter</h2>
</div>
<div class="loading" style="display: none;">
<img src="/assets/spinner.gif" alt="Spinner">
</div>
<div class="modal-target">
</div>
</div>
</div>
</div>
Notice the option element has the data-toggle='modal' attribute and the data-target of the option element matches the id of the modal div. So why doesn't the modal display when I select the option element?
Bootstrap is listening to click and tap events to trigger the opening of modal.
But <option>s are invalid targets for both events. As you can test below, they never happen:
$(window).on('click tap','option', function(e){
console.log('This will never happen!');
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<select>
<option>Option 1</option>
<option>Option 2</option>
</select>
All pointer and touch events are off on <option>s. The only one that triggers is change, but on the parent <select>.
For more details about this, see [2]nd point under Browser compatibility on MDN.
A workaround would be to get the modal data from the selected option and open the modal yourself. Looking closer, I noticed the data params on your bootstrap toggle look like params of an XhrHttpRequest. You're going to make that call yourself using params from data and parse the values in the modal on success. For now I just console.log()-ed them:
$('#global_filter_id').on('change', function(e){
let data = $(e.target).find('option:selected').data();
if (data && (data.toggle=="modal") && $('#'+data.target).is('.modal')) {
console.log(data);
// make your ajax call here and open the modal
// while waiting for results...
$('#'+data.target).modal();
}
})
$('#global_filter_id').on('change', function(e){
let data = $(e.target).find('option:selected').data();
if (data && (data.toggle=="modal") && $('#'+data.target).is('.modal')) {
console.log(data);
// make your ajax call here and open the modal
// while waiting for results...
$('#'+data.target).modal();
}
})
<link href="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/css/bootstrap.min.css" rel="stylesheet"/>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/3.3.7/js/bootstrap.min.js"></script>
<select name="global_filter_id" id="global_filter_id" data-remote="true" data-url="/contacts" data-params="card_position=card&contactable=Lead" data-type="html" class="form-control">
<option></option>
<option data-toggle="modal" data-target="filterEdit" data-url="/contacts/edit_multiple" data-remote="true" data-type="html" data-method="post" data-params="filterable_type=Lead" value="1">Edit/Delete Filter</option>
</select>
<div class="modal fade" id="filterEdit" tabindex="-1" role="dialog" aria-labelledby="myModalLabel" aria-hidden="true">
<div class="modal-dialog modal-sizer">
<div class="modal-content">
<div class="modal-header" style="overflow: auto;">
<button type="button" class="close" data-dismiss="modal"><span aria-hidden="true">×</span><span class="sr-only">Close</span></button>
<h2 class="modal-title" id="myModalLabel">Edit/Delete Filter</h2>
</div>
<div class="loading" style="display: none;">
<img src="/assets/spinner.gif" alt="Spinner">
</div>
<div class="modal-target">
</div>
</div>
</div>
</div>

Multiple Bootstrap Modals and postbacks

My knowledge in ASP.NET is very limited, yet, I am building a UI/UX design for an application that will be built in ASP MVC and I've heard rumors of the following problem:
When a Boostrap modal fires a button event (onClick), it creates a postback which in turn, it refreshes the page, thus making it impossible for multiple bootstrap modals to work. Unless the modals do not require to interact with the back end, which means they would simply serve a client-side purpose.
I need to know how much of this is true and if there is a way to create a search or populate a bootstrap modal with information being entered in a second modal.
Unfortunately, I can't produce a working ASP code but I will produce the HTML portion of it so you have an idea.
Again, my question is, can I populate modal 1 with information entered in modal 2? Modal 2 is invoked from Modal 1. See the code and Demo for details
<div class="container">
<h1>Working with Multiple Modals</h1>
<div class="margin-lg">
<button type="button" class="btn-first-modal btn btn-primary btn-lg" data-toggle="modal" data-target="#first-modal">
Launch Modal
</button>
</div>
<div class="modal" id="first-modal" data-backdrop="static" data-keyboard="false">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="close" data-dismiss="modal" aria-label="Close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title" id="myModalLabel">First Modal</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-xs-12 col-sm-4">
<label class="label-control">My ID</label>
<input type="text" class="form-control" disabled/>
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn-second-modal within-first-modal btn btn-primary">
Add ID
</button>
<button type="button" class="btn btn-default" data-dismiss="modal">Close</button>
</div>
</div>
</div>
</div>
<div class="modal" id="second-modal" data-backdrop="static" data-keyboard="false">
<div class="modal-dialog">
<div class="modal-content">
<div class="modal-header">
<button type="button" class="btn-second-modal-close close"><span aria-hidden="true">×</span></button>
<h4 class="modal-title">ID Generator</h4>
</div>
<div class="modal-body">
<div class="row">
<div class="col-xs-12 col-sm-4">
<label class="label-control">Choose ID</label>
<input type="text" class="form-control" />
</div>
</div>
</div>
<div class="modal-footer">
<button type="button" class="btn-second-modal-close btn btn-primary">Add</button>
</div>
</div>
</div>
</div>
JS
var within_first_modal = false;
$('.btn-second-modal').on('click', function() {
if ($(this).hasClass('within-first-modal')) {
within_first_modal = true;
$('#first-modal').modal('hide');
}
$('#second-modal').modal('show');
});
$('.btn-second-modal-close').on('click', function() {
$('#second-modal').modal('hide');
if (within_first_modal) {
$('#first-modal').modal('show');
within_first_modal = false;
}
});
$('.btn-toggle-fade').on('click', function() {
if ($('.modal').hasClass('fade')) {
$('.modal').removeClass('fade');
$(this).removeClass('btn-success');
} else {
$('.modal').addClass('fade');
$(this).addClass('btn-success');
}
});
DEMO
This would let you make a request to the server and do something with the information that you get back.
$(".btn-second-modal").on("click", function () {
$.ajax({
url: "/urltoserver/action/",
cache: false
}).done(function (data) {
// SET YOUR FIRST MODAL PROPERTIES
// HIDE YOUR SECOND MODAL
// SHOW YOUR FIRST MODAL
});
});

Resources